package com.yanqu.road.server.manager.unionwar;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.unionwar.UnionQunyingTimeInfo;
import com.yanqu.road.entity.activity.unionwar.cross.*;
import com.yanqu.road.entity.activity.unionwar.enums.eTimeInfoPeriodType;
import com.yanqu.road.entity.activity.unionwar.result.CurrentTimeInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eItemId;
import com.yanqu.road.entity.enums.eUnionPosition;
import com.yanqu.road.entity.enums.eUnionWarWinMark;
import com.yanqu.road.entity.log.cross.LogUnionWarActivityPatronsFight;
import com.yanqu.road.entity.log.cross.LogUnionWarActivityWinLose;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.UnionActivityRank;
import com.yanqu.road.entity.union.UnionBaseInfo;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.logic.bussiness.activity.UnionWarActivityBusiness;
import com.yanqu.road.logic.cross.CrossUnionWarRankListModel;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.logic.pb.UnionWarActivityPb;
import com.yanqu.road.logic.sort.UnionWarPatronsSort;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.unionwar.CrossUnionWarProto;
import com.yanqu.road.pb.activity.unionwar.UnionWarActivityServerProto;
import com.yanqu.road.server.CrossBaseServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.server.manager.unionwar.sort.UnionWarSortByScore1;
import com.yanqu.road.server.manager.unionwar.sort.UnionWarSortEntity;
import com.yanqu.road.server.manger.TempCommonMgr;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossUnionWarMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(CrossUnionWarMgr.class.getName());
    //活动
    private static Map<Integer, List<CrossUnionWarSimple>> unionWarSimpleMap = new ConcurrentHashMap<>();   //参赛商会基础信息
    //活动，阶段，轮次，商会
    private static Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarDetail>>>> unionWarDetailMap = new ConcurrentHashMap<>();
    /**
     * 商会状态，活动编号，阶段，轮次
     */
    private static Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarState>>>> unionWarStateMap = new ConcurrentHashMap<>();

    private static RandomHelper randomHelper = new RandomHelper();
    private static UnionWarPatronsSort unionWarPatronsSort = new UnionWarPatronsSort();




    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for(Map.Entry<Integer, List<CrossUnionWarSimple>> simpleEntry : unionWarSimpleMap.entrySet()){
            List<CrossUnionWarSimple> list = simpleEntry.getValue();
            int size = list.size();
            for(int i = 0; i < size; i++){
                CrossUnionWarSimple simple = list.get(i);
                if(simple.isInsertOption()){
                    UnionWarActivityBusiness.addCrossUnionWarSimple(simple);
                }else if(simple.isUpdateOption()){
                    UnionWarActivityBusiness.updateCrossUnionWarSimple(simple);
                }
            }
        }
        for(Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityMap : unionWarDetailMap.values()){
            Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> tempActivityMap = new ConcurrentHashMap<>(activityMap);
            for(Map<Integer, List<CrossUnionWarDetail>> stageMap : tempActivityMap.values()){
                Map<Integer, List<CrossUnionWarDetail>> tempStageMap = new ConcurrentHashMap<>(stageMap);
                for(List<CrossUnionWarDetail> roundList : tempStageMap.values()){
                    List<CrossUnionWarDetail> tempRoundList = new ArrayList<>(roundList);
                    for(CrossUnionWarDetail unionWarDetail : tempRoundList){
                        //修正
                        if(unionWarDetail.getGroupId() == 0){
                            CrossUnionWarSimple simple = getCrossUnionWarSimple(unionWarDetail.getActivityId(), unionWarDetail.getUnionUid());
                            if(simple != null && simple.getGroupId() > 0){
                                unionWarDetail.setGroupId(simple.getGroupId());
                                getLogger().info("union war repair detail stageNo {} roundNo {} unionUid {} , set groupId {}", unionWarDetail.getStageNo(), unionWarDetail.getRoundNo(), unionWarDetail.getUnionUid(), unionWarDetail.getGroupId());
                            }
                        }
                        if(unionWarDetail.isInsertOption()){
                            UnionWarActivityBusiness.addCrossUnionWarDetail(unionWarDetail);
                        }else if(unionWarDetail.isUpdateOption()){
                            UnionWarActivityBusiness.updateCrossUnionWarDetail(unionWarDetail);
                        }
                    }
                }
            }
        }
        for(Map.Entry<Integer, Map<Integer, Map<Integer, List<CrossUnionWarState>>>> activityEntry : unionWarStateMap.entrySet()){
            for(Map.Entry<Integer, Map<Integer, List<CrossUnionWarState>>> phaseEntry : activityEntry.getValue().entrySet()){
                for(Map.Entry<Integer, List<CrossUnionWarState>> sessionEntry : phaseEntry.getValue().entrySet()){
                    for (int i = 0; i < sessionEntry.getValue().size(); i++) {
                        CrossUnionWarState state = sessionEntry.getValue().get(i);
                        if(state.isInsertOption()){
                            UnionWarActivityBusiness.addCrossUnionWarState(state);
                        }else if(state.isUpdateOption()){
                            UnionWarActivityBusiness.updateCrossUnionWarState(state);
                        }
                    }
                }
            }
        }
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        reloadActivityData();
        return true;
    }

    public static void reloadActivityData() {
        List<Integer> activityIdList = new ArrayList<>(CrossUnionWarActivityMgr.getOpenActivityMap().keySet());
        Map<Integer, List<CrossUnionWarSimple>> unionWarSimpleMapTemp = UnionWarActivityBusiness.getUnionWarSimpleMap(activityIdList);
        Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarState>>>> unionWarStateMapTemp = UnionWarActivityBusiness.getUnionWarStateMap(activityIdList);
        Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarDetail>>>> unionWarDetailMapTemp = UnionWarActivityBusiness.getCrossUnionWarDetailMap(activityIdList);

        //跨服只加载，本分组数据
        int crossServerId = (int)CrossBaseServer.getInstance().getServerId();
        Map<Integer, List<String>> activityUnionListMap = new HashMap<>();
        Map<Integer, List<Integer>> activityGroupIdMap = new HashMap<>();
        for (Integer activityId : activityIdList) {
            Map<Integer, UnionActivityGroup> groupMap = Cross2UnionActivityGroupMgr.getGroupMap(activityId);
            if(groupMap != null){
                List<String> unionList = new ArrayList<>();
                List<Integer> groupList = new ArrayList<>();
                for (Map.Entry<Integer, UnionActivityGroup> groupEntry : groupMap.entrySet()) {
                    UnionActivityGroup activityGroup = groupEntry.getValue();
                    if(crossServerId == activityGroup.getCrossServerId()){
                        unionList.addAll(activityGroup.getUnionDataMap().keySet());
                        groupList.add(groupEntry.getKey());
                    }
                }
                activityUnionListMap.put(activityId, unionList);
                activityGroupIdMap.put(activityId, groupList);
            }
        }

        for (Map.Entry<Integer, List<CrossUnionWarSimple>> entry : unionWarSimpleMapTemp.entrySet()) {
            int activityId = entry.getKey();
            ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
            List<String> unionList = activityUnionListMap.get(activityId);
            if(unionList == null || unionList.size() == 0){
                if(activityInfo.getCrossId().intValue() != crossServerId) {
                    unionWarSimpleMapTemp.remove(activityId);
                }
            }else {
                entry.getValue().removeIf(simple -> !unionList.contains(simple.getUnionUid()));
            }
        }

        for (Map.Entry<Integer, Map<Integer, Map<Integer, List<CrossUnionWarState>>>> activityEntry : unionWarStateMapTemp.entrySet()) {
            for (Map.Entry<Integer, Map<Integer, List<CrossUnionWarState>>> phaseEntry : activityEntry.getValue().entrySet()) {
                for (Map.Entry<Integer, List<CrossUnionWarState>> sessionEntry : phaseEntry.getValue().entrySet()) {
                    int activityId = activityEntry.getKey();
                    ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
                    List<Integer> groupIdList = activityGroupIdMap.get(activityId);
                    if(groupIdList == null || groupIdList.size() == 0){
                        if(activityInfo.getCrossId().intValue() != crossServerId) {
                            phaseEntry.getValue().remove(sessionEntry.getKey());
                        }
                    }else {
                        sessionEntry.getValue().removeIf(state -> !groupIdList.contains(state.getGroupId()));
                    }
                }
            }
        }

        for (Map.Entry<Integer, Map<Integer, Map<Integer, List<CrossUnionWarDetail>>>> activityEntry : unionWarDetailMapTemp.entrySet()) {
            for (Map.Entry<Integer, Map<Integer, List<CrossUnionWarDetail>>> phaseEntry : activityEntry.getValue().entrySet()) {
                for (Map.Entry<Integer, List<CrossUnionWarDetail>> sessionEntry : phaseEntry.getValue().entrySet()) {
                    int activityId = activityEntry.getKey();
                    ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
                    List<String> unionList = activityUnionListMap.get(activityId);
                    if(unionList == null || unionList.size() == 0){
                        if(activityInfo.getCrossId().intValue() != crossServerId) {
                            phaseEntry.getValue().remove(sessionEntry.getKey());
                        }
                    }else {
                        sessionEntry.getValue().removeIf(state -> !unionList.contains(state.getUnionUid()));
                    }
                }
            }
        }


        unionWarSimpleMap = unionWarSimpleMapTemp;
        unionWarStateMap = unionWarStateMapTemp;
        unionWarDetailMap = unionWarDetailMapTemp;
    }

    public static Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarDetail>>>> getUnionWarDetailMap() {
        return unionWarDetailMap;
    }

    /**
     * 更新参赛商会信息
     * @param activityId
     * @param unionUid
     * @param serverId
     * @param unionBaseInfo
     */
    public static void updateUnionInfo(int activityId, String unionUid, long serverId, UnionBaseInfo unionBaseInfo, int groupId){
        List<CrossUnionWarSimple> dataList = unionWarSimpleMap.get(activityId);
        if(null == dataList){
            synchronized (unionWarSimpleMap){
                dataList = unionWarSimpleMap.get(activityId);
                if(null == dataList){
                    dataList = new ArrayList<>();
                    unionWarSimpleMap.put(activityId, dataList);
                }
            }
        }
        synchronized (dataList) {
            CrossUnionWarSimple unionWarSimple = null;
            for (CrossUnionWarSimple data : dataList) {
                if (Objects.equals(data.getUnionUid(), unionUid)) {
                    unionWarSimple = data;
                    break;
                }
            }
            if(null == unionWarSimple){
                unionWarSimple = initCrossUnionWarSimple(activityId, unionUid);
                unionWarSimple.setGroupId(groupId);
                dataList.add(unionWarSimple);
                //商会信息仅初始化，不再改变
                unionWarSimple.setUnionBaseInfo(unionBaseInfo);
            }
            //unionWarSimple.setUnionBaseInfo(unionBaseInfo);
            //unionWarSimple.setModifyTime(System.currentTimeMillis() / 1000);
        }
    }

    public static void syncUnionWarDetailAll() {
        List<CrossUnionWarDetail> syncList = new ArrayList<>();
        for (Map.Entry<Integer, Map<Integer, Map<Integer, List<CrossUnionWarDetail>>>> phaseMapEntry : unionWarDetailMap.entrySet()) {
            ActivityInfo openActivity = CrossUnionWarActivityMgr.getOpenActivity(phaseMapEntry.getKey());
            if (openActivity == null) {
                continue;
            }
            for (Map<Integer, List<CrossUnionWarDetail>> sessionMap : phaseMapEntry.getValue().values()) {
                for (List<CrossUnionWarDetail> details : sessionMap.values()) {
                    syncList.addAll(details);
                }
            }
            syncDetailToServer(phaseMapEntry.getKey(), syncList, 0L);
        }
    }

    /**
     * 更新商会详情
     * @param serverId
     * @param detailMsg
     */
    public static void updateUnionWarDetail(long serverId, CrossUnionWarProto.CrossUnionWarDetailSyncMsg detailMsg) {
        int activityId = detailMsg.getActivityId();
        int stageNo = detailMsg.getPhase();
        int roundNo = detailMsg.getSession();
        List<CrossUnionWarDetail> needSyncList = new ArrayList<>();
        for(CrossUnionWarProto.CrossUnionWarUnionDetailTempMsg unionMsg : detailMsg.getUnionDataListList()) {
            CrossUnionWarDetail data = getCrossUnionWarDetail(activityId, stageNo, roundNo, unionMsg.getUnionUid());
            if (null != data) {
                // 已经出结果的不再更新
                if(eUnionWarWinMark.Default.getValue() != data.getWinMark()){
                    continue;
                }
                synchronized (data) {
                    if(data.getGroupId() == 0){
                        CrossUnionWarSimple simple = getCrossUnionWarSimple(activityId, data.getUnionUid());
                        if(simple != null && simple.getGroupId() > 0){
                            data.setGroupId(simple.getGroupId());
                            getLogger().info("union war repair detail stageNo {} roundNo {} unionUid {} , set groupId {}", stageNo, roundNo, data.getUnionUid(), data.getGroupId());
                        }
                    }
                    BigInteger totalSilver = BigInteger.ZERO;
                    BigInteger totalAbility = BigInteger.ZERO;
                    Map<Long, UnionWarUserData> userDataMap = data.getUserDataMap();
                    List<UnionWarPatronsData> patronsDataList = data.getPatronsDataList();
                    List<UnionWarPatronsData> changePatronsDataList = new ArrayList<>();
                    for (CrossUnionWarProto.CrossUnionWarUserDetailTempMsg userMsg : unionMsg.getUserDataListList()) {
                        UnionWarUserData userData = userDataMap.get(userMsg.getUserId());
                        if (null == userData) {
                            userData = initUserUnionWarInfo(userMsg.getUserId());
                            data.addUserDataMap(userData);
                        }
                        userData.setUseItemId(userMsg.getUseItemId());
                        userData.setPosition(userMsg.getUnionPosition());
                        userData.setDonateSilver(new BigInteger(userMsg.getDonateSilver()));
                        userData.setUserBaseInfo(PlayerBasePb.parseToUserBaseInfo(userMsg.getUserBaseInfo()));
                        if(userMsg.getSendTime() > userData.getModifyTime() || userData.getModifyTime() == 0) {
                            //没被调整过的 或者 未派遣过的，就更新
                            userData.setModifyTime(userMsg.getSendTime());
                        }
                        for (CrossUnionWarProto.CrossUnionWarPatronsTempMsg patronsMsg : userMsg.getPatronsDataListList()) {
                            UnionWarPatronsData patronsData = new UnionWarPatronsData();
                            patronsData.setPatronsId(patronsMsg.getPatronsId());
                            patronsData.setPatronsLv(patronsMsg.getPatronsLv());
                            patronsData.setPatronsStageLv(patronsMsg.getPatronsStageLv());
                            patronsData.setAbility(new BigInteger(patronsMsg.getAbility()));
                            patronsData.setAbility2(new BigInteger(patronsMsg.getAbility2()));
                            patronsData.setSkinId(patronsMsg.getSkinId());
                            patronsData.setAmbush(patronsMsg.getAmbush());
                            patronsData.setUseItemId(userData.getUseItemId());
                            patronsData.setUnionPosition(userData.getPosition());
                            patronsData.setModifyTime(userData.getModifyTime());
                            patronsData.setDamage(BigInteger.ZERO);
                            patronsData.setUserId(userMsg.getUserId());
                            patronsData.setServerId(userMsg.getServerId());
                            patronsData.setSkillAddition(patronsMsg.getSkillAddition());
                            patronsData.setLianShengAddition(patronsMsg.getLianShengAddition());
                            patronsData.setPromotionId((int)patronsMsg.getPromotionId());
                            changePatronsDataList.add(patronsData);
                        }
                    }

                    changePatronsDataList(patronsDataList, changePatronsDataList, serverId);
                    for (UnionWarPatronsData unionWarPatronsData : patronsDataList) {
                        totalAbility = totalAbility.add(unionWarPatronsData.getAbility2());
                    }
                    for (UnionWarUserData warUserData : userDataMap.values()) {
                        totalSilver = totalSilver.add(warUserData.getDonateSilver());
                    }
                    data.setTotalAbility(totalAbility);
                    data.setTotalSilver(totalSilver);
                    data.addReadUserId(unionMsg.getReadUserIdList());
                    patronsDataList.sort(unionWarPatronsSort);
                    needSyncList.add(data);
                }
            }
        }
        //同步给区服
        //syncDetailToServer(activityId, needSyncList, serverId);
    }

    private static void changePatronsDataList(List<UnionWarPatronsData> oldPatronsDataList, List<UnionWarPatronsData> changePatronsDataList, long serverId) {
        oldPatronsDataList.removeIf(next -> next.getServerId() == serverId);
        oldPatronsDataList.addAll(changePatronsDataList);
    }

    public static void syncDetailToServer(int activityId, List<CrossUnionWarDetail> syncList, long selfServerId) {
        int groupId = 0;
        //同步给区服
        UnionWarActivityServerProto.CrossUnionWarDetailSync.Builder syncMsg = UnionWarActivityServerProto.CrossUnionWarDetailSync.newBuilder();
        syncMsg.setActivityId(activityId);
        for (CrossUnionWarDetail detail : syncList) {
            UnionWarActivityServerProto.CrossUnionWarDetailTemp.Builder builder = UnionWarActivityPb.buildCrossUnionWarDetailTemp(detail);
            CrossUnionWarSimple crossUnionWarSimple = getCrossUnionWarSimple(activityId, detail.getEnemyUnionUid());
            if (crossUnionWarSimple != null) {
                builder.setEnemyUnionUid(detail.getEnemyUnionUid());
                builder.setEnemyUnionInfo(UnionBasePb.parseUnionBaseTempMsg(crossUnionWarSimple.getUnionBaseInfo()));
            }
            groupId = detail.getGroupId();
            syncMsg.addDetail(builder);
        }

        //发给其他区服
        //int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(selfServerId);
        //Set<Long> needSyncServerId = CrossUnionServerGroupMgr.getGroupServer(groupId);
        ActivityInfo openActivity = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if (openActivity != null) {
            List<Long> needSyncServerId = getServerListByGroupId(openActivity, groupId);
            for (long severId : openActivity.getServerIdList()) {
                if (selfServerId != 0 && severId == selfServerId) {
                    continue;
                }
                if (!needSyncServerId.contains(severId)) {
                    continue;
                }
                YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_UNION_WAR_CROSS_SYNC_DETAIL, syncMsg);
                MessageHelper.sendPacket(severId, 0, message);
            }
        }
    }

    public static void syncAllDetailToServer(int activityId, List<String> unionUidList, long serverId) {
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> map = unionWarDetailMap.get(activityId);
        if(map == null){
            return;
        }
        CurrentTimeInfo currentTimeInfo = CrossUnionWarActivityMgr.getCurrentTimeInfo(activityId);
        if(currentTimeInfo == null || currentTimeInfo.getTimeInfo() == null){
            return;
        }
        int phase = currentTimeInfo.getTimeInfo().getType();
        int session = currentTimeInfo.getTimeInfo().getSession();
        UnionWarActivityServerProto.CrossUnionWarDetailSync.Builder syncMsg = UnionWarActivityServerProto.CrossUnionWarDetailSync.newBuilder();
        syncMsg.setActivityId(activityId);
        for (Map.Entry<Integer, Map<Integer, List<CrossUnionWarDetail>>> entry : map.entrySet()) {
            if(entry.getKey() < phase){
                continue;
            }
            Map<Integer, List<CrossUnionWarDetail>> listMap = entry.getValue();
            for (Map.Entry<Integer, List<CrossUnionWarDetail>> listEntry : listMap.entrySet()) {
                if(listEntry.getKey() + 1 < session){
                    continue;
                }
                List<CrossUnionWarDetail> list = listEntry.getValue();
                for (CrossUnionWarDetail detail : list) {
                    if (unionUidList.contains(detail.getUnionUid())) {
                        UnionWarActivityServerProto.CrossUnionWarDetailTemp.Builder builder = UnionWarActivityPb.buildCrossUnionWarDetailTemp(detail);
                        CrossUnionWarSimple crossUnionWarSimple = getCrossUnionWarSimple(activityId, detail.getEnemyUnionUid());
                        if (crossUnionWarSimple != null) {
                            builder.setEnemyUnionUid(detail.getEnemyUnionUid());
                            builder.setEnemyUnionInfo(UnionBasePb.parseUnionBaseTempMsg(crossUnionWarSimple.getUnionBaseInfo()));
                        }
                        syncMsg.addDetail(builder);
                    }
                }
            }
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_UNION_WAR_CROSS_SYNC_ALL_DETAIL, syncMsg);
        MessageHelper.sendPacket(serverId, 0, message);
    }

    /**
     * 更新商会战门客信息
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     * @param serverId
     * @param userId
     * @param patronsId
     */
    public static void updateUnionWarPatrons(int activityId, int stageNo, int roundNo, String unionUid, long serverId, long userId,
                                             int patronsId, UnionWarPatronsData patronsData){
        CrossUnionWarDetail data = getCrossUnionWarDetail(activityId, stageNo, roundNo, unionUid);
        if(null != data){
            synchronized (data){
//                Map<Long, UnionWarUserData> userDataMap = data.getUserDataMap();
//                UnionWarUserData userData = userDataMap.get(userId);
//                if(null == userData){
//                    userData = initUserUnionWarInfo(userId);
//                }
//                userData.getPatronsMap().put(patronsId, patronsData);
            }
        }
    }

    /**
     * 移除商会战门客数据
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     * @param serverId
     * @param userId
     * @param patronsId
     */
    public static void removeUnionWarPatrons(int activityId, int stageNo, int roundNo, String unionUid, long serverId, long userId, int patronsId){
        //CrossUnionWarDetail data = getCrossUnionWarDetail(activityId, stageNo, roundNo, unionUid, serverId);
        //更新信息时候不可再无数据情况下new

        //if(null != data){
        //    synchronized (data){
//                Map<Long, UnionWarUserData> userDataMap = data.getUserDataMap();
//                UnionWarUserData userData = userDataMap.get(userId);
//                if(null == userData){
//                    userData = initUserUnionWarInfo(userId);
//                }
//                userData.getPatronsMap().remove(patronsId);
         //   }
        //}
    }

    /**
     * 更新玩家商会战捐赠银两
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     * @param serverId
     * @param userId
     * @param silver
     */
    public static BigInteger updateUnionWarDonate(int activityId, int stageNo, int roundNo, String unionUid, long serverId, long userId, BigInteger silver, UserBaseInfo userBaseInfo){
        BigInteger totalSilver = BigInteger.ZERO;
        CrossUnionWarDetail data = getCrossUnionWarDetail(activityId, stageNo, roundNo, unionUid);
        if(null != data){
            synchronized (data) {
                Map<Long, UnionWarUserData> dataMap = data.getUserDataMap();
                UnionWarUserData userData = dataMap.get(userId);
                if (null == userData) {
                    userData = initUserUnionWarInfo(userId);
                    userData.setUserBaseInfo(userBaseInfo);
                    data.addUserDataMap(userData);
                }
                userData.setDonateSilver(silver);
                for(UnionWarUserData tempData : dataMap.values()){
                    totalSilver = totalSilver.add(tempData.getDonateSilver());
                }
                data.setTotalSilver(totalSilver);
            }
        }
        return totalSilver;
    }

    /**
     * 初始化玩家商会战数据
     * @param userId
     * @return
     */
    public static UnionWarUserData initUserUnionWarInfo(long userId){
        UnionWarUserData data = new UnionWarUserData();
        data.setUserId(userId);
        return data;
    }

    /**
     * 获取商会战概述
     * @param activityId
     * @param unionUid
     * @return
     */
    public static CrossUnionWarSimple getCrossUnionWarSimple(int activityId, String unionUid){
        List<CrossUnionWarSimple> dataList = getCrossUnionWarSimpleList(activityId);
        for (CrossUnionWarSimple data : dataList) {
            if (Objects.equals(data.getUnionUid(), unionUid)) {
                return data;
            }
        }
        return null;
    }

    /**
     * 获取活动商会战概述集合
     * @param activityId
     * @return
     */
    public static List<CrossUnionWarSimple> getCrossUnionWarSimpleList(int activityId){
        if(unionWarSimpleMap.containsKey(activityId)){
            return new ArrayList<>(unionWarSimpleMap.get(activityId));
        }
        return new ArrayList<>();
    }

    public static CrossUnionWarDetail initCrossUnionWarDetail(int activityId, int stageNo, int roundNo, String unionUid){
        CrossUnionWarDetail data = new CrossUnionWarDetail();
        data.setActivityId(activityId);
        data.setStageNo(stageNo);
        data.setRoundNo(roundNo);
        data.setUnionUid(unionUid);
        data.setModifyTime(System.currentTimeMillis() / 1000);
        data.setInsertOption();
        return data;
    }

    /**
     * 初始化商会战概述
     * @param activityId
     * @param unionUid
     * @return
     */
    public static CrossUnionWarSimple initCrossUnionWarSimple(int activityId, String unionUid){
        CrossUnionWarSimple data = new CrossUnionWarSimple();
        data.setActivityId(activityId);
        data.setUnionUid(unionUid);
        data.setModifyTime(System.currentTimeMillis() / 1000);
        data.setInsertOption();
        return data;
    }

    /**
     * 获取商会战详单(写)
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     * @return
     */
    public static CrossUnionWarDetail getCrossUnionWarDetail(int activityId, int stageNo, int roundNo, String unionUid){
        checkUnionWarDetail(activityId, stageNo, roundNo, unionUid);
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(null != activityDataMap) {
            Map<Integer, List<CrossUnionWarDetail>> dataMap = activityDataMap.get(stageNo);
            if (null != dataMap) {
                List<CrossUnionWarDetail> dataList = dataMap.get(roundNo);
                if (null != dataList) {
                    for (CrossUnionWarDetail data : dataList) {
                        if (null != data) {
                            if (Objects.equals(data.getUnionUid(), unionUid)) {
                                return data;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取商会战详单（只读）
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     * @return
     */
    public static CrossUnionWarDetail getCrossUnionWarDetailReadOnly(int activityId, int stageNo, int roundNo, String unionUid){
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(null != activityDataMap) {
            Map<Integer, List<CrossUnionWarDetail>> dataMap = activityDataMap.get(stageNo);
            if (null != dataMap) {
                List<CrossUnionWarDetail> dataList = dataMap.get(roundNo);
                if (null != dataList) {
                    for (CrossUnionWarDetail data : dataList) {
                        if (null != data) {
                            if (Objects.equals(data.getUnionUid(), unionUid)) {
                                return data;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取商会详单
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @return
     */
    public static List<CrossUnionWarDetail> getCrossUnionWarDetailList(int activityId, int stageNo, int roundNo, int groupId){
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(activityDataMap == null){
            return null;
        }
        Map<Integer, List<CrossUnionWarDetail>> stageDataMap = activityDataMap.get(stageNo);
        if(stageDataMap == null){
            return null;
        }
        List<CrossUnionWarDetail> dataList = stageDataMap.get(roundNo);
        if(dataList == null){
            return null;
        }
        return filterUnionDetailData(activityId, groupId, new ArrayList<>(dataList));
    }

    /**
     * 获取商会详单
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @return
     */
    public static List<CrossUnionWarDetail> getAllCrossUnionWarDetailList(int activityId, int stageNo, int roundNo){
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(activityDataMap == null){
            return null;
        }
        Map<Integer, List<CrossUnionWarDetail>> stageDataMap = activityDataMap.get(stageNo);
        if(stageDataMap == null){
            return null;
        }
        List<CrossUnionWarDetail> dataList = stageDataMap.get(roundNo);
        if(dataList == null){
            return null;
        }
        return new ArrayList<>(dataList);
    }

    /**
     * 请求决赛排行信息（客户端）
     * @param activityId
     * @param session
     */
    public static void getFinalsResultOrMatchInfo(long serverId, long playerId, int activityId, int session) {
        if(session == 0){
            return;
        }
        //客户端，按玩家
        int groupId = Cross2UnionActivityGroupMgr.getViewDataGroupId(activityId, playerId);

        int allSession = CrossUnionWarActivityMgr.getAllSession(activityId, 2);
        if(allSession > 0){
            UnionWarActivityServerProto.CrossFinalsResultOrMatchInfoRespMsg.Builder respMsg = UnionWarActivityServerProto.CrossFinalsResultOrMatchInfoRespMsg.newBuilder();
            if(allSession - session >= 3){
              List<CrossUnionWarDetail> detailList = getCrossUnionWarDetailList(activityId, 2, session, groupId);
              if(detailList != null && detailList.size() > 0){
                  Iterator<CrossUnionWarDetail> iterator = detailList.iterator();
                  while (iterator.hasNext()){
                      CrossUnionWarDetail detail = iterator.next();
                      if(detail.getNo() <= 0){
                          iterator.remove();
                      }
                  }
                  respMsg.addResult(buildFinalsResultOrMatchInfo(activityId, session, detailList));
              }
            }else {
              //最后三轮8进4进2
              for(int start = allSession - 2; start <= allSession; start++){
                  List<CrossUnionWarDetail> detailList = getCrossUnionWarDetailList(activityId, 2, start, groupId);
                  if(detailList != null && detailList.size() > 0){
                      Iterator<CrossUnionWarDetail> iterator = detailList.iterator();
                      while (iterator.hasNext()){
                          CrossUnionWarDetail detail = iterator.next();
                          if(detail.getNo() <= 0){
                              iterator.remove();
                          }
                      }
                      respMsg.addResult(buildFinalsResultOrMatchInfo(activityId, start, detailList));
                  }
              }
            }
            respMsg.setActivityId(activityId);
            respMsg.setRet(0);
            respMsg.setSession(session);
            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_UNION_WAR_ACTIVITY_FINALS_RESULT_OR_MATCH_REQ, respMsg));
        }
    }

    /**
     * 获取决赛淘汰信息
     * @param serverId
     * @param activityId
     */
    public static void getGetEliminationInfo(long serverId, int activityId) {
        //区服所有分组
        List<Integer> groupIdList = getGroupListByServerId(activityId, serverId);
        Map<String, Integer> loseSession = new HashMap<>();
        int allSession = CrossUnionWarActivityMgr.getAllSession(activityId, 2);
        for (int groupId : groupIdList) {
            for(int i = 1; i <= allSession; i++){
                List<CrossUnionWarDetail> list = getCrossUnionWarDetailList(activityId, 2, i, groupId);
                if (list != null) {
                    for(CrossUnionWarDetail detail : list){
                        if(detail.getWinMark() == eUnionWarWinMark.Lose.getValue()){
                            loseSession.put(detail.getUnionUid(), detail.getRoundNo());
                        }
                    }
                }
            }
        }
        if(loseSession.size() > 0){
            CrossUnionWarProto.CrossGetEliminationInfoRespMsg.Builder respMsg = CrossUnionWarProto.CrossGetEliminationInfoRespMsg.newBuilder();
            for(Map.Entry<String, Integer> entry : loseSession.entrySet()){
                CrossUnionWarProto.CrossUnionEliminationSessionTemp.Builder builder = CrossUnionWarProto.CrossUnionEliminationSessionTemp.newBuilder();
                builder.setUnionUid(entry.getKey());
                builder.setSession(entry.getValue());
                respMsg.addSession(builder);
            }
            respMsg.setActivityId(activityId);
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_UNION_WAR_REQ_FINALS_RESULT_FROM_CROSS, respMsg));
        }
    }

    /**
     * 构建决赛排行信息（32强、16强、8强）
     * @param activityId
     * @param session
     * @param detailList
     * @return
     */
    private static UnionWarActivityServerProto.CrossResultOrMatchInfoListTemp.Builder buildFinalsResultOrMatchInfo(int activityId, int session, List<CrossUnionWarDetail> detailList) {
        UnionWarActivityServerProto.CrossResultOrMatchInfoListTemp.Builder listBuilder = UnionWarActivityServerProto.CrossResultOrMatchInfoListTemp.newBuilder();
        listBuilder.setSession(session);
        for(CrossUnionWarDetail detail : detailList){
            //v2.6 从第二轮开始，沒有对手的就认定为被淘汰
            if(session > 1 && StringUtils.isNullOrEmpty(detail.getEnemyUnionUid())){
                continue;
            }
            UnionWarActivityServerProto.CrossResultOrMatchInfoTemp.Builder unionBuilder = UnionWarActivityServerProto.CrossResultOrMatchInfoTemp.newBuilder();
            unionBuilder.setUnionUid(detail.getUnionUid());
            CrossUnionWarSimple simple = getCrossUnionWarSimple(activityId, detail.getUnionUid());
            if(simple != null) {
                unionBuilder.setUnionInfo(UnionBasePb.parseUnionBaseTempMsg(simple.getUnionBaseInfo()));
            }
            unionBuilder.setNo(detail.getNo());
            unionBuilder.setEnemyNo(detail.getEnemyNo());
            unionBuilder.setWinMark(detail.getWinMark());
            if(!StringUtils.isNullOrEmpty(detail.getEnemyUnionUid())) {
                unionBuilder.setEnemyUnionUid(detail.getEnemyUnionUid());
            }
            listBuilder.addUnion(unionBuilder);
        }
        return listBuilder;
    }

    /**
     * 更新商会战门客信息
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @param unionUid
     */
    public static void checkUnionWarDetail(int activityId, int stageNo, int roundNo, String unionUid){
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(null == activityDataMap){
            synchronized (unionWarDetailMap){
                activityDataMap = unionWarDetailMap.get(activityId);
                if(null == activityDataMap){
                    activityDataMap = new ConcurrentHashMap<>();
                    unionWarDetailMap.put(activityId, activityDataMap);
                }
            }
        }
        Map<Integer, List<CrossUnionWarDetail>> dataMap = activityDataMap.get(stageNo);
        if(null == dataMap){
            synchronized (activityDataMap){
                dataMap = activityDataMap.get(stageNo);
                if(null == dataMap){
                    dataMap = new ConcurrentHashMap<>();
                    activityDataMap.put(stageNo, dataMap);
                }
            }
        }
        List<CrossUnionWarDetail> dataList = dataMap.get(roundNo);
        if(null == dataList){
            synchronized (dataMap){
                dataList = dataMap.get(roundNo);
                if(null == dataList){
                    dataList = new ArrayList<>();
                    dataMap.put(roundNo, dataList);
                }
            }
        }
        CrossUnionWarDetail unionWarDetail = null;
        synchronized (dataList) {
            for (CrossUnionWarDetail data : dataList) {
                if (Objects.equals(data.getUnionUid(), unionUid)) {
                    unionWarDetail = data;
                    break;
                }
            }
            if(null == unionWarDetail){
                unionWarDetail = initCrossUnionWarDetail(activityId, stageNo, roundNo, unionUid);
                dataList.add(unionWarDetail);
            }
        }
    }

    /**
     * 定时检测
     */
    public static void unionWarTimeTask(){
        try{//先进行匹配
            matchUnionTask();
        }catch (Exception e){
            logger.error("matchUnionTask except:", e);
        }
        try{//然后开战
            unionWarBattleTask();
        }catch (Exception e){
            logger.error("unionWarBattleTask except:", e);
        }
        try{//同步战斗结果（分数、排名、胜负）
            unionWarBattleResultSyncTask();
        }catch (Exception e){
            logger.error("unionWarBattleResultTask except:", e);
        }
    }

    /**
     * 检测开战
     */
    public static void unionWarBattleTask(){
        Map<Integer, ActivityInfo> activityInfoMap = CrossUnionWarActivityMgr.getOpenActivityMap();
        for(ActivityInfo activityInfo : activityInfoMap.values()){
            List<UnionQunyingTimeInfo> timeList = CrossUnionWarActivityMgr.getUnionQunyingTimeInfoList(activityInfo.getActivityId());
            for(UnionQunyingTimeInfo timeInfo : timeList) {
                if (timeInfo.getSession() == 0) {
                    continue;
                }
                if(!CrossUnionWarActivityMgr.isUnionWarBattleTime(activityInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession())) {//在开战时间
                    continue;
                }
                List<Integer> groupIdList = getGroupListByCrossServerId(activityInfo.getActivityId(), CrossBaseServer.getInstance().getServerId());
                for (int groupId : groupIdList) {
                    CrossUnionWarState unionWarState = getCrossUnionWarState(timeInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession(), groupId);
                    if(null != unionWarState){
                        if(unionWarState.getState() == 1){//已经匹配期了，开战
                            boolean result = dealBattle(activityInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession(), groupId);
                            if(result){//战斗完成
                                unionWarState.setState(2);
                                syncUnionWarBattleResult(activityInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession(), groupId);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 积分赛积分排序
     */
    private static void sortScorePhaseRank(int activityId, int groupId) {
        List<CrossUnionWarSimple> unionList = getCrossUnionWarSimpleList(activityId);
        unionList = filterUnionData(activityId, groupId, unionList);
        List<UnionWarSortEntity> list = new ArrayList<>();
        for(CrossUnionWarSimple union : unionList){
            list.add(new UnionWarSortEntity(union.getUnionUid()));
        }
        UnionWarSortByScore1 sort = new UnionWarSortByScore1(activityId);
        list.sort(sort);
        int i = 1;
        for(UnionWarSortEntity entity : list){
            CrossUnionWarSimple simple = getCrossUnionWarSimple(activityId, entity.getUnionUid());
            simple.setNo(i);
            i++;

            //积分排行榜
            UnionActivityRank unionRank = new UnionActivityRank(activityId, groupId);
            unionRank.setValue(BigInteger.valueOf(simple.getScore1()));
            unionRank.setUnionUid(simple.getUnionUid());
            unionRank.setPhase(1);
            unionRank.setGroupId(groupId);
            unionRank.setUnionBaseInfo(simple.getUnionBaseInfo());
            CrossUnionWarRankMgr.changeUnionWarRank(activityId, 1, unionRank, false, groupId);
        }
    }

    /**
     * 决赛胜场排序
     */
    private static void sortFinalsPhaseRank(int activityId, int groupId) {
        UnionQunyingTimeInfo qunyingTimeInfo = CrossUnionWarActivityMgr.getUnionQunyingTimeInfo(activityId, 2, 0);
        //积分赛前n名进入决赛
        int finalsNum = 0;
        if(qunyingTimeInfo != null){
            finalsNum = Integer.valueOf(qunyingTimeInfo.getParam());
        }
        List<CrossUnionWarSimple> unionList = getCrossUnionWarSimpleList(activityId);
        unionList = filterUnionData(activityId, groupId, unionList);
        for(CrossUnionWarSimple simple : unionList){
            //进入决赛的商会才冲榜
            if(simple.getNo() > finalsNum){
                continue;
            }

            //排行榜
            UnionActivityRank unionRank = new UnionActivityRank(activityId, groupId);
            unionRank.setValue(BigInteger.valueOf(simple.getScore2()));
            unionRank.setUnionUid(simple.getUnionUid());
            unionRank.setPhase(2);
            unionRank.setGroupId(groupId);
            unionRank.setUnionBaseInfo(simple.getUnionBaseInfo());
            CrossUnionWarRankMgr.changeUnionWarRank(activityId, 2, unionRank, false, groupId);
        }
    }


    /**
     * 获取冠军商会
     * @param activityId
     * @return
     */
    public static CrossUnionWarSimple getChampion(int activityId, int groupId){
        int allSession = CrossUnionWarActivityMgr.getAllSession(activityId, 2);
        CrossUnionWarState state = getCrossUnionWarState(activityId, 2, allSession, groupId);
        if(state != null && state.getState() == 2) {
            List<CrossUnionWarDetail> detailList = getCrossUnionWarDetailList(activityId, 2, allSession, groupId);
            if (detailList != null){
                for(CrossUnionWarDetail detail : detailList){
                    if(detail.getWinMark() == eUnionWarWinMark.Win.getValue()){
                        CrossUnionWarSimple simple = CrossUnionWarMgr.getCrossUnionWarSimple(activityId, detail.getUnionUid());
                        return simple;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取前几名商会
     */
    public static List<String> getTopUnions(int activityId, int lowestRank, int groupId) {
        int allSession = CrossUnionWarActivityMgr.getAllSession(activityId, 2);
        CrossUnionWarState state = getCrossUnionWarState(activityId, 2, allSession, groupId);
        if(state != null && state.getState() == 2) {
            CrossUnionWarRankListModel rankListModel = CrossUnionWarRankMgr.getCrossUnionWarRankListModel(activityId, 2, groupId);
            List<String> unionUidList = new ArrayList<>();
            if (rankListModel != null) {
                LinkedList<UnionActivityRank> rankList = rankListModel.getRankList();
                int rankNum = lowestRank <= rankList.size() ? lowestRank : rankList.size();
                for (int i = 0; i < rankNum; i++) {
                    if (rankList.get(i) != null) {
                        unionUidList.add(rankList.get(i).getUnionUid());
                    } else {
                        logger.error("群英活动 id {} 第{}名数据异常", activityId, i + 1);
                        return null;
                    }
                }
                return unionUidList;
            }
        }
        return null;
    }
    /**
     * 同步战斗结果回区服
     */
    public static void unionWarBattleResultSyncTask(){
        Map<Integer, ActivityInfo> activityInfoMap = CrossUnionWarActivityMgr.getOpenActivityMap();
        for(ActivityInfo activityInfo : activityInfoMap.values()) {
            List<UnionQunyingTimeInfo> timeList = CrossUnionWarActivityMgr.getUnionQunyingTimeInfoList(activityInfo.getActivityId());
            for(UnionQunyingTimeInfo timeInfoConfig : timeList) {
                if(timeInfoConfig.getSession() == 0){
                    continue;
                }
                List<Integer> groupIdList = getGroupListByCrossServerId(activityInfo.getActivityId(), (int)CrossBaseServer.getInstance().getServerId());
                for (int groupId : groupIdList) {
                    CrossUnionWarState unionWarState = getCrossUnionWarState(activityInfo.getActivityId(), timeInfoConfig.getType(), timeInfoConfig.getSession(), groupId);
                    if(null == unionWarState || unionWarState.getState() < 2){//还未完成战斗
                        continue;
                    }
                    //计分
                    calculateScores(activityInfo.getActivityId(), timeInfoConfig.getType(), timeInfoConfig.getSession(), groupId);
                    sendBattleResultToServer(activityInfo.getActivityId(), timeInfoConfig.getType(), timeInfoConfig.getSession(), groupId);
                }
            }
        }
    }

    /**
     * 同步战斗结果回区服
     */
    private static void sendBattleResultToServer(int activityId, int type, int session, int groupId) {
        List<CrossUnionWarDetail> detailList = getCrossUnionWarDetailList(activityId, type, session, groupId);
//        Map<Long, List<CrossUnionWarProto.CroUnionWarBattleResultTemp>> serverMap = new HashMap<>();
        Map<Long, List<CrossUnionWarProto.CroUnionWarBattleResultTemp>> syncMap = new ConcurrentHashMap<>();
        ActivityInfo openActivity = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if (openActivity == null) {
            return;
        }
        if(detailList != null) {
           for(CrossUnionWarDetail detail : detailList) {
               CrossUnionWarSimple unionWarSimple1 = getCrossUnionWarSimple(activityId, detail.getUnionUid());
               if(unionWarSimple1 == null){
                   continue;
               }
//               long serverId = unionWarSimple1.getUnionBaseInfo().getServerId();
//               int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
//               Set<Long> needSyncServerId = CrossUnionServerGroupMgr.getGroupServer(groupId);
               List<Long> needSyncServerId = getServerListByGroupId(openActivity, groupId);
               if(detail.getResultSync().size() >= needSyncServerId.size() || detail.getWinMark() == 0 || !detail.isAddScore()) {  //未计分也不同步
                   continue;
               }
//               if(!serverMap.containsKey(detail.getServerId())){
//                   serverMap.put(detail.getServerId(), new ArrayList<>());
//               }
               CrossUnionWarProto.CroUnionWarBattleResultTemp.Builder resultBuilder = CrossUnionWarProto.CroUnionWarBattleResultTemp.newBuilder();
               resultBuilder.setWinMark(detail.getWinMark());
               resultBuilder.setUnionUid(detail.getUnionUid());
               if(detail.getEnemyUnionUid() != null){
                   resultBuilder.setEnemyUnionUid(detail.getEnemyUnionUid());
                   CrossUnionWarSimple unionWarSimple = getCrossUnionWarSimple(activityId, detail.getEnemyUnionUid());
                   resultBuilder.setEnemyBaseInfo(UnionBasePb.parseUnionBaseTempMsg(unionWarSimple.getUnionBaseInfo()));
               }
               CrossUnionWarSimple unionWarSimple = getCrossUnionWarSimple(activityId, detail.getUnionUid());
               if(unionWarSimple != null){
                   resultBuilder.setScore1(unionWarSimple.getScore1());
                   resultBuilder.setScore2(unionWarSimple.getScore2());
                   resultBuilder.setRank1(unionWarSimple.getNo());
                   resultBuilder.setRank2(0);
               }
//               serverMap.get(detail.getServerId()).add(resultBuilder.build());
               for (long needServerId : needSyncServerId) {
                   if (!detail.getResultSync().contains(needServerId)) {
                       if (!syncMap.containsKey(needServerId)) {
                           syncMap.put(needServerId, new ArrayList<>());
                       }
                       syncMap.get(needServerId).add(resultBuilder.build());
                   }
               }
           }
        }
        for(Map.Entry<Long, List<CrossUnionWarProto.CroUnionWarBattleResultTemp>> entry : syncMap.entrySet()){
            CrossUnionWarProto.CrossUnionWarBattleResultSendMsg.Builder sendMsg = CrossUnionWarProto.CrossUnionWarBattleResultSendMsg.newBuilder();
            sendMsg.setActivityId(activityId);
            sendMsg.setPhase(type);
            sendMsg.setSession(session);
            sendMsg.addAllResult(entry.getValue());
            sendMsg.setGroupId(groupId);
            MessageHelper.sendPacket(entry.getKey(), 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_UNION_WAR_BATTLE_RESULT_SYNC_FORM_CROSS, sendMsg));
            logger.info("battle result sync {} size {}, phase {} session {}", entry.getKey(), sendMsg.getResultList().size(), type, session);
        }
    }

    /**
     * 匹配商会
     */
    public static void matchUnionTask(){
        Map<Integer, ActivityInfo> activityInfoMap = CrossUnionWarActivityMgr.getOpenActivityMap();
        for(ActivityInfo activityInfo : activityInfoMap.values()){
            //活动分组
            List<Integer> groupIdList = getGroupListByCrossServerId(activityInfo.getActivityId(), CrossBaseServer.getInstance().getServerId());
            List<UnionQunyingTimeInfo> timeList = CrossUnionWarActivityMgr.getUnionQunyingTimeInfoList(activityInfo.getActivityId());
            try{
                //备战期，全匹配
                if(CrossUnionWarActivityMgr.isScoreMatchUnionTime(activityInfo.getActivityId())) {
                    for (int groupId : groupIdList) {
                        dealScoreStageMatch(activityInfo.getActivityId(), groupId);
                    }
                }
            }catch(Exception e){
                logger.error(e.getMessage(), e);
            }
            for(UnionQunyingTimeInfo timeInfo : timeList){
                if(timeInfo.getSession() == 0){//
                    continue;
                }
                for (int groupId : groupIdList) {
                    CrossUnionWarState unionWarState = getCrossUnionWarState(timeInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession(), groupId);
                    if(null != unionWarState){
                        if(unionWarState.getState() == 0){//还没匹配，进行匹配
                            if(!CrossUnionWarActivityMgr.isMatchUnionTime(activityInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession())) {//在匹配对手商会时间
                                continue;
                            }
                            boolean isMatch = dealMatch(unionWarState.getActivityId(), unionWarState.getStageNo(), unionWarState.getRoundNo(), groupId);
                            if(isMatch) {
                                unionWarState.setState(1); //匹配完成
                            }
                        }else if(unionWarState.getState() == 1){
                            //下发
                            sendMatchInfoToServer(activityInfo.getActivityId(), timeInfo.getType(), timeInfo.getSession(), groupId);
                        }
                    }
                }
            }
        }
    }

    /**
     * 下发对阵
     * @param activityId
     * @param type
     * @param session  场次
     */
    private static void sendMatchInfoToServer(int activityId, int type, int session, int groupId) {
        ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if(activityInfo == null){
            return;
        }
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> typeSessionMap = unionWarDetailMap.get(activityId);
        Map<Long, List<CrossUnionWarProto.CroUnionWarMatchInfoTemp>> syncMsgMap = new ConcurrentHashMap<>();
        ActivityInfo openActivity = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if (openActivity == null) {
            return;
        }
        if(typeSessionMap != null){
            Map<Integer, List<CrossUnionWarDetail>> sessionMap = typeSessionMap.get(type);
            if(sessionMap != null && sessionMap.containsKey(session)){
                List<CrossUnionWarDetail> list = sessionMap.get(session);
                int size = list.size();
                for(int i = 0; i < size; i++){
                    CrossUnionWarDetail detail = list.get(i);
                    CrossUnionWarSimple unionWarSimple1 = getCrossUnionWarSimple(activityId, detail.getUnionUid());
                    if(unionWarSimple1 == null){
                        continue;
                    }
//                    long serverId = unionWarSimple1.getUnionBaseInfo().getServerId();
//                    int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
//                    Set<Long> needSyncServerId = CrossUnionServerGroupMgr.getGroupServer(groupId);
                    List<Long> needSyncServerId = getServerListByGroupId(activityInfo, groupId);
                    if(detail.getMatchSync().size() >= needSyncServerId.size()) {
                        continue;
                    }
//                    if(!serverMap.containsKey(detail.getServerId())){
//                        serverMap.put(detail.getServerId(), new ArrayList<>());
//                    }
                    CrossUnionWarProto.CroUnionWarMatchInfoTemp.Builder builder = CrossUnionWarProto.CroUnionWarMatchInfoTemp.newBuilder();
                    builder.setUnionUid(detail.getUnionUid());
//                    builder.setEnemyServerId(detail.getEnemyServerId());
                    if(!StringUtils.isNullOrEmpty(detail.getEnemyUnionUid())) {
                        builder.setEnemyUnionUid(detail.getEnemyUnionUid());
                    }
                    builder.setWinMark(detail.getWinMark());
                    CrossUnionWarSimple unionWarSimple = getCrossUnionWarSimple(activityId, detail.getEnemyUnionUid());
                    if(unionWarSimple != null){
                        builder.setEnemyBaseInfo(UnionBasePb.parseUnionBaseTempMsg(unionWarSimple.getUnionBaseInfo()));
                        builder.setEnemyUnionUid(detail.getEnemyUnionUid());
                    }
//                    serverMap.get(detail.getServerId()).add(builder.build());
                    for (Long needServerId : needSyncServerId) {
                        if (!detail.getMatchSync().contains(needServerId)) {
                            if (!syncMsgMap.containsKey(needServerId)) {
                                syncMsgMap.put(needServerId, new ArrayList<>());
                            }
                            syncMsgMap.get(needServerId).add(builder.build());
                        }
                    }
                }
            }
        }


        for(Map.Entry<Long, List<CrossUnionWarProto.CroUnionWarMatchInfoTemp>> entry : syncMsgMap.entrySet()){
            CrossUnionWarProto.CrossUnionWarMatchInfoSendMsg.Builder sendMsg = CrossUnionWarProto.CrossUnionWarMatchInfoSendMsg.newBuilder();
            sendMsg.setActivityId(activityId);
            sendMsg.setPhase(type);
            sendMsg.setSession(session);
            sendMsg.addAllMatch(entry.getValue());
            sendMsg.setGroupId(groupId);
            MessageHelper.sendPacket(entry.getKey(), 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_UNION_WAR_MATCH_INFO_SYNC_FORM_CROSS, sendMsg));
            logger.info("match enemy sync {} size {}, phase {} session {}", entry.getKey(), sendMsg.getMatchList().size(), type, session);
        }
    }

    //对阵匹配结果下发（区服响应）
    public static void updateMatchInfoSendResult(long serverId, int activityId, int phase, int session, List<String> unionUidList, int groupId) {
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> typeSessionMap = unionWarDetailMap.get(activityId);
        if(typeSessionMap != null) {
            Map<Integer, List<CrossUnionWarDetail>> sessionMap = typeSessionMap.get(phase);
            if (sessionMap != null && sessionMap.containsKey(session)) {
                List<CrossUnionWarDetail> list = sessionMap.get(session);
                if (list == null || list.isEmpty()) {
                    return;
                }
                int size = list.size();
                for (int i = 0; i < size; i++) {
                    CrossUnionWarDetail detail = list.get(i);
                    if (detail.getGroupId() != groupId) {
                        continue;
                    }
                    if (detail.getMatchSync().contains(serverId)) {
                        continue;
                    }
                    synchronized (detail.getMatchSync()) {
                        if (detail.getMatchSync().contains(serverId)) {
                            continue;
                        }
                        if(unionUidList.contains(detail.getUnionUid())){
                            detail.addMatchSyncServerId(serverId);
                        }
                    }
                }
            }
        }
    }

    //对阵结果下发（区服响应）
    public static void updateBattleResultSendResult(long serverId, int activityId, int phase, int session, List<String> unionUidList, int groupId) {
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> typeSessionMap = unionWarDetailMap.get(activityId);
        if(typeSessionMap != null) {
            Map<Integer, List<CrossUnionWarDetail>> sessionMap = typeSessionMap.get(phase);
            if (sessionMap != null && sessionMap.containsKey(session)) {
                List<CrossUnionWarDetail> list = sessionMap.get(session);
                if (list == null || list.isEmpty()) {
                    return;
                }
                int size = list.size();
                for (int i = 0; i < size; i++) {
                    CrossUnionWarDetail detail = list.get(i);
                    if (detail.getGroupId() != groupId) {
                        continue;
                    }

                    if (detail.getResultSync().contains(serverId)) {
                        continue;
                    }
                    synchronized (detail.getResultSync()) {
                        if (detail.getResultSync().contains(serverId)) {
                            continue;
                        }
                        if(unionUidList.contains(detail.getUnionUid())){
                            detail.addResultSync(serverId);
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理开战逻辑
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @return
     */
    private static boolean dealBattle(int activityId, int stageNo, int roundNo, int groupId){
        ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if(null == activityInfo){//已经结束的活动
            return false;
        }
        List<Integer> paramList = StringUtils.stringToIntegerList(activityInfo.getParam4(), ";");
        if(paramList.size() < 2){
            return false;
        }
        UnionQunyingTimeInfo unionQunyingTimeInfo = CrossUnionWarActivityMgr.getUnionQunyingTimeInfo(activityId, stageNo, roundNo);
        if(unionQunyingTimeInfo == null){
            return false;
        }
        List<Integer> scoreList = StringUtils.stringToIntegerList(unionQunyingTimeInfo.getScore(), "\\|");
        if(scoreList.size() != 2){
            return false;
        }
        Map<Integer, Map<Integer, List<CrossUnionWarDetail>>> activityDataMap = unionWarDetailMap.get(activityId);
        if(null == activityDataMap) {
            return false;
        }
        Map<Integer, List<CrossUnionWarDetail>> stageDataMap = activityDataMap.get(stageNo);
        if (null == stageDataMap) {
            return false;
        }
        List<CrossUnionWarDetail> dataList = getCrossUnionWarDetailList(activityId, stageNo, roundNo, groupId);

        if (null == dataList || dataList.size() == 0) {
            return false;
        }
//        for(CrossUnionWarDetail detail : dataList){
//            if(detail.getMatchSync() == 0){
//                //本场次匹配阵容未全部同步，等待,
//                //return false;
//                //照打，不能限制
//            }
//        }
        //胜利的派遣  v2.6
        List<CrossUnionWarDetail> winDetailList = new ArrayList<>();
        List<CrossUnionWarDetail> cloneDetailList = new ArrayList<>(dataList);
        //按门客总能力排序一下，精彩对阵
        cloneDetailList.sort((o1, o2) -> o2.getTotalAbility().compareTo(o1.getTotalAbility()));
        int topMatchCount = 0;
        int maxTopMatchCount = unionQunyingTimeInfo.getMatchVideo();
        logger.info("activityId {} phase {} session {} battle start ", activityId, stageNo, roundNo);
        while (cloneDetailList.size() > 0){
            CrossUnionWarDetail unionWarDetail = cloneDetailList.get(0);
            if(unionWarDetail.getWinMark() == eUnionWarWinMark.Bye.getValue() || StringUtils.isNullOrEmpty(unionWarDetail.getEnemyUnionUid())){//轮空
                cloneDetailList.remove(unionWarDetail);
                //addScore(activityId, stageNo, scoreList, unionWarDetail, null);
                continue;
            }
            CrossUnionWarDetail enemyUnionWarDetail = null;
            for(CrossUnionWarDetail tempData : cloneDetailList){
                if(Objects.equals(tempData.getUnionUid(), unionWarDetail.getEnemyUnionUid())){
                    enemyUnionWarDetail = tempData;
                    break;
                }
            }

            logger.info("{} vs {} ", unionWarDetail.getUnionUid(), enemyUnionWarDetail.getUnionUid());
            int silverAddition1 = 0;
            int silverAddition2 = 0;
            logger.info("{} 银两 {}", unionWarDetail.getUnionUid(), unionWarDetail.getTotalSilver().longValue());
            logger.info("{} 银两 {}", enemyUnionWarDetail.getUnionUid(), enemyUnionWarDetail.getTotalSilver().longValue());
            int silverCompareValue = unionWarDetail.getTotalSilver().compareTo(enemyUnionWarDetail.getTotalSilver());
            if(silverCompareValue > 0){
                silverAddition1 = paramList.get(0);
            }else if(silverCompareValue < 0){
                silverAddition2 = paramList.get(0);
            }else{
                //银两也平手或者都没捐募 按商会赚钱
                CrossUnionWarSimple unionWarSimple = getCrossUnionWarSimple(activityId, unionWarDetail.getUnionUid());
                CrossUnionWarSimple enemyUnionWarSimple = getCrossUnionWarSimple(activityId, enemyUnionWarDetail.getUnionUid());
                if(unionWarSimple !=null && enemyUnionWarSimple != null){
                    if(unionWarSimple.getUnionBaseInfo().getTotalEarnSpeed().compareTo(enemyUnionWarSimple.getUnionBaseInfo().getTotalEarnSpeed()) >= 0){
                        silverAddition1 = paramList.get(0);
                    }else {
                        silverAddition2 = paramList.get(0);
                    }
                }
            }
            List<UnionWarPatronsData> patronsDataList = getBattlePatronsDataList(unionWarDetail);
            List<UnionWarPatronsData> enemyPatronsDataList = getBattlePatronsDataList(enemyUnionWarDetail);
            int index1 = -1;
            int index2 = -1;
            UnionWarPatronsData patronsData1 = null;
            UnionWarPatronsData patronsData2 = null;
            boolean isPush1 = true;
            boolean isPush2 = true;
            boolean isUseJn1 = false;
            boolean isUseJn2 = false;
            boolean isWin = false;
            do {
                if (isPush1) {//我方退场
                    index1++;
                    logger.info("{}", unionWarDetail.getUnionUid());
                    patronsData1 = getUnionWarPatronsDataByIndex(activityInfo, unionWarDetail, silverAddition1, patronsDataList, index1);
                    if(patronsData1 != null)
                        logger.info("门客[{}]-{} 出场，血量{}，当前伤害{}，锦囊 {}, 银两加成{}", index1, patronsData1.getPatronsId(),
                                patronsData1.getBlood().longValue(),patronsData1.getDamage().longValue(), patronsData1.getUseItemId(), silverAddition1);
                    isUseJn1 = false;//门客替换重置锦囊使用状态
                    isPush1 = false;
                }
                if (isPush2) {//对方退场
                    index2++;
                    logger.info("{}", enemyUnionWarDetail.getUnionUid());
                    patronsData2 = getUnionWarPatronsDataByIndex(activityInfo, enemyUnionWarDetail, silverAddition2, enemyPatronsDataList, index2);
                    if(patronsData2 != null)
                        logger.info("门客[{}]-{} 出场，血量{}，当前伤害{}，锦囊 {}, 银两加成{}", index2, patronsData2.getPatronsId(),
                                patronsData2.getBlood().longValue(), patronsData2.getDamage().longValue(), patronsData2.getUseItemId(), silverAddition2);
                    isUseJn2 = false;
                    isPush2 = false;
                }
                if(null == patronsData1 && null == patronsData2){//都没派门客，平手,按银两即银两加成
                    if(silverAddition1 > 0){
                        logger.info("{} 胜", unionWarDetail.getUnionUid());
                        isWin = true;
                    }else if(silverAddition2 > 0){
                        logger.info("{} 胜", enemyUnionWarDetail.getUnionUid());
                        isWin = false;
                    }else {

                    }
                    break;
                }else if(null == patronsData1){//己方没派门客，输
                    logger.info("{} 胜", enemyUnionWarDetail.getUnionUid());
                    isWin = false;
                    break;
                }else if(null == patronsData2){//对方没派门客，赢
                    logger.info("{} 胜", unionWarDetail.getUnionUid());
                    isWin = true;
                    break;
                }
                long logPatronsData1Blold = patronsData1.getBlood().longValue();
                long logPatronsData2Blold = patronsData2.getBlood().longValue();

                //减对面门客能力处理
                if(!isUseJn1) {
                    logger.info("{}", unionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 使用能言善变锦囊，敌方门客[{}]-{}", index1, patronsData1.getPatronsId(), index2, patronsData2.getPatronsId());
                    nysbEffectPatronsData(patronsData1, patronsData2);
                    logger.info("门客[{}]-{} 血量{}， 伤害{}", index1, patronsData1.getPatronsId(), patronsData1.getBlood().longValue(), patronsData1.getDamage().longValue());
                    isUseJn1 = true;
                }
                logger.info(" ");
                if(!isUseJn2) {
                    logger.info("{}", enemyUnionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 使用能言善变锦囊，敌方门客[{}]-{}", index2, patronsData2.getPatronsId(), index1, patronsData1.getPatronsId());
                    nysbEffectPatronsData(patronsData2, patronsData1);
                    logger.info("门客[{}]-{} 血量{}， 伤害{}", index2, patronsData2.getPatronsId(), patronsData2.getBlood().longValue(), patronsData2.getDamage().longValue());
                    isUseJn2 = true;
                }

                int compareValue = patronsData1.getBlood().compareTo(patronsData2.getBlood());
                if(compareValue > 0){
                    isPush1 = dealPatronsBattleWin(patronsData1, patronsData2);
                    logger.info("{}", unionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 胜，血量{}， 伤害{}, 连胜{}，是否退出[{}]", index1, patronsData1.getPatronsId(), patronsData1.getBlood().longValue(),
                            patronsData1.getDamage().longValue(), patronsData1.getWinTimes(), isPush1);
                    patronsData2.setDamage(patronsData2.getDamage().add(patronsData2.getBlood()));
                    patronsData2.setBlood(BigInteger.ZERO);
                    isPush2 = true;

                    //unionWarDetail 门客胜
                    //enemyUnionWarDetail 门客负/退出

                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, unionWarDetail.getUnionUid(), stageNo, roundNo, patronsData1.getUserId(), patronsData1.getPatronsId(),
                            index1, patronsData1.getBlood().longValue(), logPatronsData1Blold, true, patronsData1.getWinTimes(), enemyUnionWarDetail.getUnionUid(),
                            patronsData2.getUserId(), patronsData2.getPatronsId(), patronsData2.getBlood().longValue(), logPatronsData2Blold));

                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, enemyUnionWarDetail.getUnionUid(), stageNo, roundNo, patronsData2.getUserId(), patronsData2.getPatronsId(),
                            index2, patronsData2.getBlood().longValue(), logPatronsData2Blold, false, patronsData2.getWinTimes(), unionWarDetail.getUnionUid(),
                            patronsData1.getUserId(), patronsData1.getPatronsId(), patronsData1.getBlood().longValue(), logPatronsData1Blold));

                    logger.info("{}", enemyUnionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 败，血量{}， 伤害{}, 连胜{}，退出", index2, patronsData2.getPatronsId(), patronsData2.getBlood().longValue(),
                            patronsData2.getDamage().longValue(), patronsData2.getWinTimes());
                }else if(0 == compareValue){
                    patronsData1.setDamage(patronsData1.getDamage().add(patronsData1.getBlood()));
                    patronsData1.setBlood(BigInteger.ZERO);
                    patronsData1.setWinTimes(patronsData1.getWinTimes() + 1);
                    isPush1 = true;
                    logger.info("{}", unionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 败，血量{}， 伤害{}, 连胜{}，退出", index1, patronsData1.getPatronsId(), patronsData1.getBlood().longValue(),
                            patronsData1.getDamage().longValue(), patronsData1.getWinTimes());
                    patronsData2.setDamage(patronsData2.getDamage().add(patronsData2.getBlood()));
                    patronsData2.setBlood(BigInteger.ZERO);
                    patronsData2.setWinTimes(patronsData2.getWinTimes() + 1);
                    isPush2 = true;
                    logger.info("{}", enemyUnionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 败，血量{}， 伤害{}, 连胜{}，退出", index2, patronsData2.getPatronsId(), patronsData2.getBlood().longValue(),
                            patronsData2.getDamage().longValue(), patronsData2.getWinTimes());

                    //同时退出
                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, unionWarDetail.getUnionUid(), stageNo, roundNo, patronsData1.getUserId(), patronsData1.getPatronsId(),
                            index1, patronsData1.getBlood().longValue(), logPatronsData1Blold, false, patronsData1.getWinTimes(), enemyUnionWarDetail.getUnionUid(),
                            patronsData2.getUserId(), patronsData2.getPatronsId(), patronsData2.getBlood().longValue(), logPatronsData2Blold));

                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, enemyUnionWarDetail.getUnionUid(), stageNo, roundNo, patronsData2.getUserId(), patronsData2.getPatronsId(),
                            index2, patronsData2.getBlood().longValue(), logPatronsData2Blold, false, patronsData2.getWinTimes(), unionWarDetail.getUnionUid(),
                            patronsData1.getUserId(), patronsData1.getPatronsId(), patronsData1.getBlood().longValue(), logPatronsData1Blold));

                }else {
                    isPush2 = dealPatronsBattleWin(patronsData2, patronsData1);
                    logger.info("{}", enemyUnionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 胜，血量{}， 伤害{}, 连胜{}，是否退出[{}]", index2, patronsData2.getPatronsId(), patronsData2.getBlood().longValue(),
                            patronsData2.getDamage().longValue(), patronsData2.getWinTimes(), isPush2);
                    patronsData1.setDamage(patronsData1.getDamage().add(patronsData1.getBlood()));
                    patronsData1.setBlood(BigInteger.ZERO);


                    //enemyUnionWarDetail 门客胜
                    //unionWarDetail 门客负/退出
                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, enemyUnionWarDetail.getUnionUid(), stageNo, roundNo, patronsData2.getUserId(), patronsData2.getPatronsId(),
                            index2, patronsData2.getBlood().longValue(), logPatronsData2Blold, true, patronsData2.getWinTimes(), unionWarDetail.getUnionUid(),
                            patronsData1.getUserId(), patronsData1.getPatronsId(), patronsData1.getBlood().longValue(), logPatronsData1Blold));

                    //打斗日志
                    CrossAutoLogMgr.add(new LogUnionWarActivityPatronsFight(activityId, unionWarDetail.getUnionUid(), stageNo, roundNo, patronsData1.getUserId(), patronsData1.getPatronsId(),
                            index1, patronsData1.getBlood().longValue(), logPatronsData1Blold, false, patronsData1.getWinTimes(), enemyUnionWarDetail.getUnionUid(),
                            patronsData2.getUserId(), patronsData2.getPatronsId(), patronsData2.getBlood().longValue(), logPatronsData2Blold));

                    isPush1 = true;
                    logger.info("{}", unionWarDetail.getUnionUid());
                    logger.info("门客[{}]-{} 败，血量{}， 伤害{}, 连胜{}，退出", index1, patronsData1.getPatronsId(), patronsData1.getBlood().longValue(),
                            patronsData1.getDamage().longValue(), patronsData1.getWinTimes());
                }
            } while (true);

            if(isWin){//获胜
                unionWarDetail.setWinMark(eUnionWarWinMark.Win.getValue());
                enemyUnionWarDetail.setWinMark(eUnionWarWinMark.Lose.getValue());
                //积分
                //addScore(activityId, stageNo, scoreList, unionWarDetail, enemyUnionWarDetail);
                winDetailList.add(unionWarDetail);
                try {
                    //胜日志
                    addWinLog(activityId, unionWarDetail.getUnionUid(), stageNo, roundNo, enemyUnionWarDetail.getUnionUid(), unionWarDetail.getTotalSilver().toString(), silverAddition1 > 0);
                    //负
                    addLoseLog(activityId, enemyUnionWarDetail.getUnionUid(), stageNo, roundNo, unionWarDetail.getUnionUid(), enemyUnionWarDetail.getTotalSilver().toString(), silverAddition2 > 0);
                }catch (Exception e){
                    logger.error(e.getMessage(), e);
                }

            }else{
                unionWarDetail.setWinMark(eUnionWarWinMark.Lose.getValue());
                enemyUnionWarDetail.setWinMark(eUnionWarWinMark.Win.getValue());
                //积分
                //addScore(activityId, stageNo, scoreList, enemyUnionWarDetail, unionWarDetail);
                winDetailList.add(enemyUnionWarDetail);
                try {
                    //胜日志
                    addWinLog(activityId, enemyUnionWarDetail.getUnionUid(), stageNo, roundNo, unionWarDetail.getUnionUid(), enemyUnionWarDetail.getTotalSilver().toString(), silverAddition2 > 0);
                    //负
                    addLoseLog(activityId, unionWarDetail.getUnionUid(), stageNo, roundNo, enemyUnionWarDetail.getUnionUid(), unionWarDetail.getTotalSilver().toString(), silverAddition1 > 0);
                }catch (Exception e){
                    logger.error(e.getMessage(), e);
                }
            }
            unionWarDetail.setPatronsDataList(patronsDataList);
            enemyUnionWarDetail.setPatronsDataList(enemyPatronsDataList);
            cloneDetailList.remove(unionWarDetail);
            cloneDetailList.remove(enemyUnionWarDetail);
        }
        //v2.6
        //按门客总能力排序一下，精彩对阵
        winDetailList.sort((o1, o2) -> o2.getTotalAbility().compareTo(o1.getTotalAbility()));
        for(CrossUnionWarDetail win : winDetailList){
            if(topMatchCount < maxTopMatchCount){
                win.setTopMatch(true);
                topMatchCount++;
                CrossUnionWarDetail enemyDetail = getCrossUnionWarDetail(activityId, stageNo, roundNo, win.getEnemyUnionUid());
                if(enemyDetail.getWinMark() == eUnionWarWinMark.Lose.getValue()){
                    enemyDetail.setTopMatch(true);
                }
            }
        }
        return true;
    }

    //胜日志
    private static void addWinLog(int activityId, String unionUid, int stageNo, int roundNo, String enemyUnionUid, String totalSilver, boolean silverWin){
        CrossAutoLogMgr.add(new LogUnionWarActivityWinLose(activityId, unionUid, stageNo, roundNo, totalSilver, silverWin,
                true, enemyUnionUid));
    }

    //负
    private static void addLoseLog(int activityId, String unionUid, int stageNo, int roundNo, String enemyUnionUid, String totalSilver, boolean silverWin){
        CrossAutoLogMgr.add(new LogUnionWarActivityWinLose(activityId, unionUid, stageNo, roundNo, totalSilver, silverWin,
                false, enemyUnionUid));
    }

    /**
     * 计分
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    private static void calculateScores(int activityId, int stageNo, int roundNo, int groupId) {
        //v2.6 限制过早计分
        CurrentTimeInfo currentTimeInfo = CrossUnionWarActivityMgr.getCurrentTimeInfo(activityId);
        UnionQunyingTimeInfo now = currentTimeInfo.getTimeInfo();
        if(now != null && now.getType() == stageNo && now.getSession() == roundNo && currentTimeInfo.getPeriodType() == eTimeInfoPeriodType.FightingTime
            && !currentTimeInfo.isBeforeDurTimeTwoMin(CrossUnionWarActivityMgr.getOpenActivity(activityId))){
            //场次处于战斗期的暂不计分
            return;
        }
        UnionQunyingTimeInfo unionQunyingTimeInfo = CrossUnionWarActivityMgr.getUnionQunyingTimeInfo(activityId, stageNo, roundNo);
        if(unionQunyingTimeInfo == null){
            return;
        }
        List<Integer> scoreList = StringUtils.stringToIntegerList(unionQunyingTimeInfo.getScore(), "\\|");
        if(scoreList.size() != 2){
            return;
        }
        List<CrossUnionWarDetail> dataList = getCrossUnionWarDetailList(activityId, stageNo, roundNo, groupId);
        if (null == dataList || dataList.size() == 0) {
            return;
        }
        int size = dataList.size();
        boolean change = false;
        for(int i = 0; i < size; i++){
            CrossUnionWarDetail detail = dataList.get(i);
            if(detail.isAddScore() || detail.getWinMark() == eUnionWarWinMark.Default.getValue()){
                continue;
            }
            if(detail.getWinMark() == eUnionWarWinMark.Bye.getValue()){
                addScore(activityId, stageNo, detail, scoreList.get(0), 2);
                detail.setAddScore(true);
                change = true;
            }else if(detail.getWinMark() == eUnionWarWinMark.Win.getValue()){
                addScore(activityId, stageNo, detail, scoreList.get(0), 2);
                detail.setAddScore(true);
                change = true;
            }else if(detail.getWinMark() == eUnionWarWinMark.Lose.getValue()){
                addScore(activityId, stageNo, detail, scoreList.get(1), 1);
                detail.setAddScore(true);
                change = true;
            }
        }
        if(change){
            if(stageNo == 1) {
                sortScorePhaseRank(activityId, groupId);
            }else if(stageNo == 2) {
                sortFinalsPhaseRank(activityId, groupId);
            }
        }
    }


    /**
     * 按对战结果加积分
     * @param activityId
     * @param stageNo
     * @param detail
     * @param score
     */
    private static void addScore(int activityId, int stageNo, CrossUnionWarDetail detail, int score, int score2) {
        CrossUnionWarSimple simple = getCrossUnionWarSimple(activityId, detail.getUnionUid());
        if(simple != null){
            if(stageNo == 1){
                simple.setScore1(simple.getScore1() + score);
            }else {
                simple.setScore2(simple.getScore2() + score2);//胜场
            }
        }
    }

    /**
     * 通过下标获取门客数据
     * @param activityInfo
     * @param unionWarDetail
     * @param silverAddition
     * @param patronsDataList
     * @param index
     * @return
     */
    private static UnionWarPatronsData getUnionWarPatronsDataByIndex(ActivityInfo activityInfo, CrossUnionWarDetail unionWarDetail,
                                                                     int silverAddition, List<UnionWarPatronsData> patronsDataList, int index) {
        UnionWarPatronsData patronsData1;
        if (index < patronsDataList.size()) {
            patronsData1 = patronsDataList.get(index);
            patronsData1 = dealPatronsData(patronsData1, unionWarDetail, silverAddition, activityInfo);
        } else {
            patronsData1 = null;
        }
        return patronsData1;
    }

    /**
     * 处理胜利门客数据
     * @param patronsData1
     * @param patronsData2
     * @return
     */
    private static boolean dealPatronsBattleWin(UnionWarPatronsData patronsData1, UnionWarPatronsData patronsData2){
        boolean isPush = false;      //是否退场
        patronsData1.setBlood(patronsData1.getBlood().subtract(patronsData2.getBlood()));
        patronsData1.setWinTimes(patronsData1.getWinTimes() + 1);
        patronsData1.setDamage(patronsData1.getDamage().add(patronsData2.getBlood()));
        if(patronsData1.getWinTimes() >= patronsData1.getMaxWinTimes() ||
                patronsData1.getUseItemId() == eItemId.UNION_WAR_ACTIVITY_BSYZ_JN.getValue()){//退场
            isPush = true;
        }
        return isPush;
    }

    /**
     * 减门客能力锦囊效果
     * @param patronsData1
     * @param patronsData2
     */
    private static void nysbEffectPatronsData(UnionWarPatronsData patronsData1, UnionWarPatronsData patronsData2){
        if(patronsData1.getUseItemId() == eItemId.UNION_WAR_ACTIVITY_NYSB_JN.getValue()){//减对面能力
            BigInteger oldBlood = patronsData2.getBlood();
            BigDecimal blood = new BigDecimal(patronsData2.getBlood());
            GoodsInfo goodsInfo = TempCommonMgr.getGoodsInfo(eItemId.UNION_WAR_ACTIVITY_NYSB_JN.getValue());
            if(null != goodsInfo) {
                int addition = goodsInfo.getParamList().get(0).intValue();
                blood = blood.multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
            }
            patronsData2.setBlood(blood.toBigInteger());
            BigInteger damage = oldBlood.subtract(patronsData2.getBlood());
            patronsData1.setDamage(patronsData1.getDamage().add(damage));
            logger.info("能言善变锦囊 {}, 伤害 {}", patronsData1.getUseItemId(), damage.longValue());
        }
    }

    /**
     * 商会职能影响门客能力
     * @param position
     * @param activityInfo
     */
    private static int unionPositionEffectPatronsData(int position, ActivityInfo activityInfo){
        List<Integer> paramList = StringUtils.stringToIntegerList(activityInfo.getParam3(), "\\|");
        int addition;
        if(position == eUnionPosition.Master.getValue()){
            addition = paramList.get(0);
        }else if(position == eUnionPosition.DeputyMaster.getValue()){
            addition = paramList.get(1);
        }else if(position == eUnionPosition.Elite.getValue()){
            addition = paramList.get(2);
        }else {
            addition = paramList.get(3);
        }
        return addition;
    }

    /**
     * 处理门客数据
     * @param patronsData
     * @param unionWarDetail
     * @param silverAddition
     * @return
     */
    private static UnionWarPatronsData dealPatronsData(UnionWarPatronsData patronsData, CrossUnionWarDetail unionWarDetail, int silverAddition,
                                                       ActivityInfo activityInfo){
        if(null == patronsData){
            return null;
        }
        UnionWarUserData userData = unionWarDetail.getUserDataMap().get(patronsData.getUserId());
        BigDecimal blood = new BigDecimal(patronsData.getAbility());
        //职能加成
        int totalAddition = 0;
        int positionAddition = unionPositionEffectPatronsData(userData.getPosition(), activityInfo);
        totalAddition += positionAddition;
        logger.info("门客 -{} 职位加成 {} ：{} - {}", patronsData.getPatronsId(), positionAddition + "/1000", patronsData.getAbility().intValue(), blood.longValue());
        totalAddition += silverAddition;
        //银两比拼加成
        logger.info("门客 -{} 银两加成 {} ：{} - {}", patronsData.getPatronsId(), silverAddition + "/1000", patronsData.getBlood().intValue(), blood.longValue());
        totalAddition += patronsData.getSkillAddition();
        // 天赋加成
        logger.info("门客 -{} 天赋加成 {} ：{} - {}", patronsData.getPatronsId(), patronsData.getSkillAddition() + "/1000", patronsData.getBlood().intValue(), blood.longValue());

        blood = blood.multiply(BigDecimal.valueOf(1000 + totalAddition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
        List<Integer> paramList = StringUtils.stringToIntegerList(activityInfo.getParam4(), ";");
        int maxWinTimes = paramList.get(1); //默认连胜次数
        //门客技能加成连胜次数
        int lianShengAddition = patronsData.getLianShengAddition();
        int lianShengTimes = maxWinTimes + lianShengAddition;
        logger.info("门客 -{} 连胜次数技能加成 {} ：{} - {}", patronsData.getPatronsId(), lianShengAddition, maxWinTimes, lianShengTimes);
        patronsData.setMaxWinTimes(lianShengTimes);

        //锦囊效果(势如破竹改为赚钱效果，但与背水一战不同的是可以连胜)
        if(userData.getUseItemId() == eItemId.UNION_WAR_ACTIVITY_SRPZ_JN.getValue()){//加赚钱
            GoodsInfo goodsInfo = TempCommonMgr.getGoodsInfo(eItemId.UNION_WAR_ACTIVITY_SRPZ_JN.getValue());
            if(null != goodsInfo) {
                int addition = goodsInfo.getParamList().get(0).intValue();
                blood = blood.multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
                logger.info("门客 -{} 势如破竹加成 {} ：{} - {}", patronsData.getPatronsId(), addition + "/1000", patronsData.getBlood().intValue(), blood.longValue());
            }
        }else if(userData.getUseItemId() == eItemId.UNION_WAR_ACTIVITY_BSYZ_JN.getValue()){//加赚钱
            GoodsInfo goodsInfo = TempCommonMgr.getGoodsInfo(eItemId.UNION_WAR_ACTIVITY_BSYZ_JN.getValue());
            if(null != goodsInfo) {
                int addition = goodsInfo.getParamList().get(0).intValue();
                blood = blood.multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
                logger.info("门客 -{} 背水一战加成 {} ：{} - {}", patronsData.getPatronsId(), addition + "/1000", patronsData.getBlood().intValue(), blood.longValue());
            }
        }
        patronsData.setBlood(blood.toBigInteger());
        patronsData.setUseItemId(userData.getUseItemId());
        return patronsData;
    }

    /**
     * 获取出战门客集合（进行出战排序）
     * @param unionWarDetail
     * @return
     */
    private static List<UnionWarPatronsData> getBattlePatronsDataList(CrossUnionWarDetail unionWarDetail){
        List<UnionWarPatronsData> dataList = new ArrayList<>(unionWarDetail.getPatronsDataList());
        Iterator<UnionWarPatronsData> iterator = dataList.iterator();
        //伏兵
        List<UnionWarPatronsData> ambushList = new ArrayList<>();
        //移出伏兵
        while (iterator.hasNext()){
            UnionWarPatronsData temp = iterator.next();
            if(temp.getAmbush() == 1){
                ambushList.add(temp);
                iterator.remove();
            }
        }
        dataList.sort(unionWarPatronsSort);
        //插入伏兵
        for (UnionWarPatronsData ambush : ambushList) {
            //查找派遣位置
            int idx = -1;
            for (int i = 0; i < dataList.size(); i++) {
                UnionWarPatronsData noAmbush = dataList.get(i);
                if(ambush.getUserId() == noAmbush.getUserId()){
                    idx = i;
                    break;
                }
            }
            if(idx != -1){
                if(idx + 1 < dataList.size()) {
                    dataList.add(idx + 1, ambush);
                }else {
                    dataList.add(ambush);
                }
            }
        }
        return dataList;
    }

    /**
     * 处理商会匹配
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    public static boolean dealMatch(int activityId, int stageNo, int roundNo, int groupId){
        if(1 == stageNo){
            return false;
        }else {
            return dealFinalStageMatch(activityId, stageNo, roundNo, groupId);
        }
    }

    /**
     * 检测是否所有区服都已上传商会信息
     * @param activityId
     * @return
     */
//    private static boolean isAllServerUploadUnionInfo(int activityId, List<CrossUnionWarSimple> unionList){
//        ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
//        if(activityInfo == null){
//            return false;
//        }
//        List<Long> serverList = new ArrayList<>(activityInfo.getServerIdList());
//        Set<Long> serverIdSet = new HashSet<>();
//        serverIdSet.addAll(serverList);
//        for(CrossUnionWarSimple unionWarSimple : unionList){
//            if(serverIdSet.contains(unionWarSimple.getServerId())){
//                serverIdSet.remove(unionWarSimple.getServerId());
//            }
//        }
//        if(serverIdSet.size() == 0){
//            return true;
//        }
//        logger.error("union war activity {} no union of server {}  ", activityId, serverIdSet.toString());
//        return false;
//    }

    /**
     * 全局匹配（对手无重复）
     * @param activityId
     * @return 本次是否成功
     */
    private static boolean dealScoreStageMatch(int activityId, int groupId){
        //所有商会
        List<CrossUnionWarSimple> unionList = getCrossUnionWarSimpleList(activityId);
        unionList = filterUnionData(activityId, groupId, unionList);
        int unionSize = unionList.size();
        //商会数量不是偶数直接返回
        if((unionSize % 2 == 1) || unionSize <= 0){
            logger.error("activity {} union size {} error", activityId, unionList.size());
            return false;
        }
        //积分赛所有场次
        int allSession = CrossUnionWarActivityMgr.getAllSession(activityId, 1);
        if(allSession >= unionList.size()){
            logger.error("activity {} allSession {} >= union size {} error", activityId, allSession, unionList.size());
            return false;
        }
        //有未匹配的场次，则全部重新匹配
        boolean matched = true;
        for(int session = 1; session <= allSession; session++) {
            CrossUnionWarState unionWarState = getCrossUnionWarState(activityId, 1, session, groupId);
            if(unionWarState.getState() == 0){
                matched = false;
                break;
            }
        }
        if(matched){
            return false;
        }

//        boolean allIn = isAllServerUploadUnionInfo(activityId, unionList);
//        if(!allIn){
//            return false;
//        }
        //生成随机配对表
        boolean randomSuccess = false;
        int[][] table = new int[allSession][unionList.size()];
        //本次最多尝试100次
        for(int i= 0; i< 100; i++){
            try {
                logger.info("activity {} try match times {}", activityId, i);
                table = MatchEnemySimulate.randomMatchInNSessionV26(allSession, unionList.size());
            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }
            if(MatchEnemySimulate.isAllFill(table)){
                MatchEnemySimulate.randomExchangeRow(table);
                randomSuccess = true;
                logger.info("match success");
                MatchEnemySimulate.print(table);
                break;
            }else {
                table = new int[allSession][unionList.size()];
            }
        }
        if(!randomSuccess){
            //下次重试
            return false;
        }
        //商会按赚钱降序排开
        List<CrossUnionWarSimple> tempList = new ArrayList<>(unionList);
        Collections.sort(tempList, new Comparator<CrossUnionWarSimple>() {
            @Override
            public int compare(CrossUnionWarSimple o1, CrossUnionWarSimple o2) {
                return o1.getUnionBaseInfo().getTotalEarnSpeed().compareTo(o2.getUnionBaseInfo().getTotalEarnSpeed());
            }
        });
        for(int session = 1; session <= allSession; session++) {
            for (int i = 0; i < unionSize; i++) {
                CrossUnionWarSimple union = tempList.get(i);
                CrossUnionWarSimple enemyUnion = tempList.get(table[session-1][i]-1);

                CrossUnionWarDetail unionWarDetail1 = getCrossUnionWarDetail(activityId, 1, session, union.getUnionUid());
                //CrossUnionWarDetail unionWarDetail2 = getCrossUnionWarDetail(activityId, 1, session, enemyUnion.getUnionUid(),
                //        enemyUnion.getServerId());
                //设置对手商会
                unionWarDetail1.setEnemyUnionUid(enemyUnion.getUnionUid());
                //unionWarDetail2.setEnemyUnionUid(union.getUnionUid());
                //unionWarDetail2.setEnemyServerId(union.getServerId());
            }
            CrossUnionWarState unionWarState = getCrossUnionWarState(activityId, 1, session, groupId);
            //设置场次状态
            unionWarState.setState(1);
        }
        return true;
    }

    /**
     * 处理积分赛阶段匹配(按场次，对手会重复)
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    private static boolean dealScoreStageMatch(int activityId, int stageNo, int roundNo){
        List<CrossUnionWarSimple> unionList = getCrossUnionWarSimpleList(activityId);
        if((unionList.size() % 2 == 1) || unionList.size() <= 0){//商会数量不是偶数直接返回
            logger.error("activity {} stateNo {} roundNo {} union size {}", activityId, stageNo, roundNo, unionList.size());
            return false;
        }
//        boolean allIn = isAllServerUploadUnionInfo(activityId, unionList);
//        if(!allIn){
//            return false;
//        }
        List<CrossUnionWarSimple> tempList = new ArrayList<>(unionList);
        List<CrossUnionWarSimple> randomUnionList = new ArrayList<>();
        while (tempList.size() > 0){
            int randomValue = randomHelper.next(0, tempList.size());
            CrossUnionWarSimple data = tempList.get(randomValue);
            randomUnionList.add(data);
            tempList.remove(data);
        }
        for(int i = 0; i < randomUnionList.size(); i = i + 2){
            CrossUnionWarSimple union1 = randomUnionList.get(i);
            CrossUnionWarSimple union2 = randomUnionList.get(i + 1);
            CrossUnionWarDetail unionWarDetail1 = getCrossUnionWarDetail(activityId, stageNo, roundNo, union1.getUnionUid());
            CrossUnionWarDetail unionWarDetail2 = getCrossUnionWarDetail(activityId, stageNo, roundNo, union2.getUnionUid());
            //设置对手商会
            unionWarDetail1.setEnemyUnionUid(union2.getUnionUid());
            unionWarDetail2.setEnemyUnionUid(union1.getUnionUid());
        }
        return true;
    }

    /**
     * 获取商会当前决赛轮次的对手编号
     * @param n  配置进入决赛商会数 n
     * @param allRound 所有轮次
     * @param round 当前轮次
     * @param no  商会起始编号或者排名
     * @param size 当前轮次参与的商会数
     * @return 0,轮空
     */
    public static int getWarEnemyNo(int n, int allRound, int round, int no, int size){
        int m = allRound;
        if(1 << m < n){
            m = m + 1;
        }
        int needSize = 1 << (m - round + 1);
        if(size < needSize && no <= (needSize - size)){ //第一轮,前几名轮空
            return 0;
        }
        return needSize - no + 1;
    }

    /**
     * 处理决赛阶段匹配
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    private static boolean dealFinalStageMatch(int activityId, int stageNo, int roundNo, int groupId){
        List<CrossUnionWarSimple> unionList = getCrossUnionWarSimpleList(activityId);
        unionList = filterUnionData(activityId, groupId, unionList);
        if((unionList.size() % 2 == 1) || unionList.size() <= 0){//商会数量不是偶数直接返回
            logger.error("activity {} stateNo {} roundNo {} groupId {} union size {}", activityId, stageNo, roundNo, groupId, unionList.size());
            return false;
        }
        UnionQunyingTimeInfo unionQunyingTimeInfo = CrossUnionWarActivityMgr.getUnionQunyingTimeInfo(activityId, 2, 0);
        if(unionQunyingTimeInfo == null){
            return false;
        }
        int n = Integer.valueOf(unionQunyingTimeInfo.getParam());
        int allRound = CrossUnionWarActivityMgr.getAllSession(activityId, stageNo);
        //校验
        int m = allRound;
        if(1 << m < n){
            logger.error("activityId {} TimeInfo config error, m {}, n {}", activityId, m, n);
            return false;
        }
        List<CrossUnionWarDetail> detailList = new ArrayList<>();
        if(stageNo == 2 && roundNo == 1){
            //检测积分赛最后一场是否已开战
            CrossUnionWarState crossUnionWarState = getCrossUnionWarState(activityId, 1, CrossUnionWarActivityMgr.getAllSession(activityId, 1), groupId);
            if(crossUnionWarState.getState() != 2){
                return false;
            }
            //检测积分赛最后一场是否都已积分
            List<CrossUnionWarDetail> lastList = getCrossUnionWarDetailList(activityId, 1, CrossUnionWarActivityMgr.getAllSession(activityId, 1), groupId);
            for(CrossUnionWarDetail detail : lastList){
                if(!detail.isAddScore()){
                    return false;
                }
            }
            //第一轮，取积分赛排名(有轮空)，生成备战数据，下发区服
            List<CrossUnionWarSimple> all = new ArrayList<>();
            //no, union
            Map<Integer, CrossUnionWarSimple> allMap = new HashMap<>();
            //sortScorePhaseRank(activityId); //没必要
            for(CrossUnionWarSimple entity : unionList){
                if(entity.getNo() <= n){
                    all.add(entity);
                    allMap.put(entity.getNo(), entity);
                }
            }
            if(all.size() > 0 && all.size() % 2 == 0) {
                int size = all.size();
                for (int j = 0; j < size; j++) {
                    CrossUnionWarSimple union = all.get(j);
                    CrossUnionWarDetail unionWarDetail = getCrossUnionWarDetail(activityId, stageNo, roundNo, union.getUnionUid());
                    int enemyNo = getWarEnemyNo(n, allRound, roundNo, union.getNo(), all.size());
                    if (enemyNo == 0) {
                        //轮空
                        unionWarDetail.setNo(union.getNo());
                        unionWarDetail.setEnemyNo(enemyNo);
                        unionWarDetail.setWinMark(eUnionWarWinMark.Bye.getValue());
                    } else {
                        CrossUnionWarSimple enemyUnion = allMap.get(enemyNo);
                        unionWarDetail.setNo(union.getNo());
                        unionWarDetail.setEnemyNo(enemyNo);
                        detailList.add(unionWarDetail);
                        //设置对手商会
                        unionWarDetail.setEnemyUnionUid(enemyUnion.getUnionUid());
                    }
                }
                //下发备战数据给屈服
                sendMatchInfoToServer(activityId, stageNo, roundNo, groupId);

                //v2.6需求，决赛阶段可备战所有场次
                initOtherSessionDispatchDetail(activityId, allRound, all, groupId);
                return true;
            }
        }else if(stageNo == 2 && roundNo > 1){
            //检测上一场是否已开战
            CrossUnionWarState crossUnionWarState = getCrossUnionWarState(activityId, stageNo, roundNo - 1, groupId);
            if(crossUnionWarState.getState() != 2){
                return false;
            }
            //其他轮次，取上一轮次胜负
            List<CrossUnionWarDetail> lastDetailList = getCrossUnionWarDetailList(activityId, stageNo, roundNo - 1, groupId);
            if(lastDetailList != null){
                Map<Integer, CrossUnionWarDetail> noMap = new HashMap<>();
                for(CrossUnionWarDetail lastDetail : lastDetailList){
                    if(lastDetail.getWinMark() == eUnionWarWinMark.Bye.getValue() || lastDetail.getWinMark() == eUnionWarWinMark.Win.getValue()){
                        //本轮备战
                        CrossUnionWarDetail unionWarDetail = getCrossUnionWarDetail(activityId, stageNo, roundNo, lastDetail.getUnionUid());
                        if(lastDetail.getNo() > lastDetail.getEnemyNo() && lastDetail.getEnemyNo() > 0){
                            unionWarDetail.setNo(lastDetail.getEnemyNo());  //继承编号
                        }else {
                            unionWarDetail.setNo(lastDetail.getNo());
                        }
                        noMap.put(unionWarDetail.getNo(), unionWarDetail);
                        detailList.add(unionWarDetail);
                    }
                }
                //不是偶数或者大小是0
                if(detailList.size() % 2 != 0 || detailList.size() == 0){
                    logger.error("activity {} stateNo {} roundNo {} union size {}", activityId, stageNo, roundNo, detailList.size());
                    return false;
                }
                //设置对手
                int size = detailList.size();
                for(int j = 0; j < size; j++){
                    CrossUnionWarDetail unionWarDetail = detailList.get(j);
                    int enemyNo = getWarEnemyNo(n, allRound, roundNo, unionWarDetail.getNo(), detailList.size());
                    CrossUnionWarDetail enemyUnion = noMap.get(enemyNo);
                    unionWarDetail.setEnemyNo(enemyNo);
                    //设置对手商会
                    unionWarDetail.setEnemyUnionUid(enemyUnion.getUnionUid());
                    synchronized (unionWarDetail.getMatchSync()) {
                        unionWarDetail.getMatchSync().clear();//重置0，开启重新同步对手数据， v2.6
                    }
                }
                //下发备战数据给区服
                sendMatchInfoToServer(activityId, stageNo, roundNo, groupId);
                return true;
            }
        }
        return false;
    }

    /**
     *  下发决赛其他场次的备战（预先），只对进入决赛的商会;v2.6
     * @param activityId
     * @param allRound  决赛场次
     * @param all  进入决赛的商会
     */
    private static void initOtherSessionDispatchDetail(int activityId, int allRound, List<CrossUnionWarSimple> all, int groupId) {
        for(int s = 2; s <= allRound; s++){
            int size = all.size();
            for (int j = 0; j < size; j++) {
                CrossUnionWarSimple union = all.get(j);
                //初始备战数据
                getCrossUnionWarDetail(activityId, 2, s, union.getUnionUid());
            }
            sendMatchInfoToServer(activityId, 2, s, groupId);
        }
    }


    /**
     * 获取对战场次当前状态
     * @param activityId
     * @param stageNo
     * @param roundNo
     * @return
     */
    public static CrossUnionWarState getCrossUnionWarState(int activityId, int stageNo, int roundNo, int groupId){
        Map<Integer, Map<Integer, List<CrossUnionWarState>>> stageDataMap = unionWarStateMap.get(activityId);
        if(null == stageDataMap){
            synchronized (unionWarStateMap){
                if(!unionWarStateMap.containsKey(activityId)){
                    unionWarStateMap.put(activityId, new ConcurrentHashMap<>());
                }
            }
            stageDataMap = unionWarStateMap.get(activityId);
        }
        Map<Integer, List<CrossUnionWarState>> roundDataMap = stageDataMap.get(stageNo);
        if(null == roundDataMap){
            synchronized (stageDataMap){
                if(!stageDataMap.containsKey(stageNo)){
                    stageDataMap.put(stageNo, new ConcurrentHashMap<>());
                }
            }
            roundDataMap = stageDataMap.get(stageNo);
        }
        List<CrossUnionWarState> unionWarStateList = roundDataMap.get(roundNo);
        if(unionWarStateList == null){
            synchronized (roundDataMap){
                if(!roundDataMap.containsKey(roundNo)){
                    roundDataMap.put(roundNo, new ArrayList<>());
                }
            }
            unionWarStateList = roundDataMap.get(roundNo);
        }
        CrossUnionWarState unionWarState = null;
        synchronized (unionWarStateList){
            for (CrossUnionWarState state : unionWarStateList) {
                if(state.getGroupId() == groupId){
                    unionWarState = state;
                    break;
                }
            }
            if(unionWarState == null){
                unionWarState = new CrossUnionWarState();
                unionWarState.setActivityId(activityId);
                unionWarState.setStageNo(stageNo);
                unionWarState.setRoundNo(roundNo);
                unionWarState.setInsertOption();
                unionWarState.setGroupId(groupId);
                unionWarStateList.add(unionWarState);
            }
        }
        return unionWarState;
    }

    /**
     * 构建商会战结果
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    public static CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder getUnionWarBattleResultMsg(int activityId, int stageNo, int roundNo, int groupId){
        CrossUnionWarState unionWarState = getCrossUnionWarState(activityId, stageNo, roundNo, groupId);
        if(null == unionWarState){
            return null;
        }
        if(unionWarState.getState() < 2){//还未完成战斗
            return null;
        }
        List<CrossUnionWarDetail> unionWarDetailList = getCrossUnionWarDetailList(activityId, stageNo, roundNo, groupId);
        if(null == unionWarDetailList || unionWarDetailList.size() == 0){
            return null;
        }
        CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder syncMsg = CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.setPhase(stageNo);
        syncMsg.setSession(roundNo);
        syncMsg.setGroupId(groupId);
        for(CrossUnionWarDetail unionWarDetail : unionWarDetailList){
            if(unionWarDetail.getGroupId() != groupId){
                continue;
            }
            if(unionWarDetail.getWinMark() == 0){
                continue;
            }
            CrossUnionWarProto.CrossUnionWarUnionBattleTempMsg.Builder unionMsg = parseBattleResultBuilder(activityId, stageNo, roundNo, unionWarDetail);
            syncMsg.addUnionDataList(unionMsg);
        }
        return syncMsg;
    }

    public static CrossUnionWarProto.CrossUnionWarUnionBattleTempMsg.Builder parseBattleResultBuilder(int activityId, int stageNo, int roundNo, CrossUnionWarDetail unionWarDetail) {
        CrossUnionWarProto.CrossUnionWarUnionBattleTempMsg.Builder unionMsg = CrossUnionWarProto.CrossUnionWarUnionBattleTempMsg.newBuilder();
        unionMsg.setUnionUid(unionWarDetail.getUnionUid());
        CrossUnionWarSimple unionWarSimple = getCrossUnionWarSimple(activityId, unionWarDetail.getUnionUid());
        unionMsg.setUnionBaseInfo(UnionBasePb.parseUnionBaseTempMsg(unionWarSimple.getUnionBaseInfo()));
        unionMsg.setWinMark(unionWarDetail.getWinMark());
        unionMsg.setIsTopMatch(unionWarDetail.isTopMatch());
        unionMsg.setTeamEarnSpeed(unionWarDetail.getTotalAbility().toString());//v2.6
        if(unionWarDetail.getWinMark() != eUnionWarWinMark.Bye.getValue()){//不是轮空
            unionMsg.setEnemyUnionUid(unionWarDetail.getEnemyUnionUid());
            CrossUnionWarSimple enemyUnionWarSimple = getCrossUnionWarSimple(activityId, unionWarDetail.getEnemyUnionUid());
            unionMsg.setEnemyUnionBaseInfo(UnionBasePb.parseUnionBaseTempMsg(enemyUnionWarSimple.getUnionBaseInfo()));
            CrossUnionWarDetail enemyDetail = getCrossUnionWarDetail(activityId, stageNo, roundNo, enemyUnionWarSimple.getUnionUid());
            if(enemyDetail != null){
                //v2.6
                unionMsg.setEnemyTeamEarnSpeed(enemyDetail.getTotalAbility().toString());
            }
        }
        for(UnionWarUserData userData : unionWarDetail.getUserDataMap().values()){
            CrossUnionWarProto.CrossUnionWarUserBattleTempMsg.Builder userMsg = CrossUnionWarProto.CrossUnionWarUserBattleTempMsg.newBuilder();
            userMsg.setUserId(userData.getUserId());
            userMsg.setUnionPosition(userData.getPosition());
            userMsg.setDonateSilver(userData.getDonateSilver().toString());
            userMsg.setUseItemId(userData.getUseItemId());
            userMsg.setIsQuitUnion(userData.isQuitUnion());
            if(userData.getUserBaseInfo() != null){
                userMsg.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userData.getUserBaseInfo()));
            }
            unionMsg.addUserDataList(userMsg);
        }
        for(UnionWarPatronsData patronsData : getBattlePatronsDataList(unionWarDetail)){
            CrossUnionWarProto.CrossUnionWarPatronsBattleTempMsg.Builder patronsMsg = CrossUnionWarProto.CrossUnionWarPatronsBattleTempMsg.newBuilder();
            patronsMsg.setUserId(patronsData.getUserId());
            patronsMsg.setPatronsId(patronsData.getPatronsId());
            patronsMsg.setPatronsLv(patronsData.getPatronsLv());
            patronsMsg.setPatronsStageLv(patronsData.getPatronsStageLv());
            patronsMsg.setSkinId(patronsData.getSkinId());
            patronsMsg.setAmbush(patronsData.getAmbush());
            patronsMsg.setUseItemId(patronsData.getUseItemId());
            patronsMsg.setAbility(patronsData.getAbility().toString());
            patronsMsg.setDamage(patronsData.getDamage().toString());
            patronsMsg.setWinTimes(patronsData.getWinTimes());
            patronsMsg.setUnionPosition(patronsData.getUnionPosition());
            patronsMsg.setSkillAddition(patronsData.getSkillAddition());
            patronsMsg.setLianShengAddition(patronsData.getLianShengAddition());
            patronsMsg.setPromotionId(patronsData.getPromotionId());
            unionMsg.addPatronsDataList(patronsMsg);
        }
        unionMsg.setNo(unionWarDetail.getNo());
        unionMsg.setEnemyNo(unionWarDetail.getEnemyNo());
        return unionMsg;
    }

    /**
     * 同步商会战结果
     * @param activityId
     * @param stageNo
     * @param roundNo
     */
    private static void syncUnionWarBattleResult(int activityId, int stageNo, int roundNo, int groupId){
        ActivityInfo activityInfo = CrossUnionWarActivityMgr.getOpenActivity(activityId);
        if(null == activityInfo){
            return;
        }
        CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder syncMsg = getUnionWarBattleResultMsg(activityId, stageNo, roundNo, groupId);
        if(null == syncMsg){
            return;
        }
        syncMsg.setGroupId(groupId);
        for(long serverId : getServerListByGroupId(activityInfo, groupId)) {
            //CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder tempMsg = filterUnionWarBattleResultMsg(serverId, syncMsg);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_UNION_WAR_RESULT_SYNC_FORM_CROSS, syncMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    /**
     * 过滤商会战斗
     * @param serverId
     * @param syncMsg
     * @return
     */
    public static CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder filterUnionWarBattleResultMsg(long serverId,
            CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder syncMsg){
//        CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.Builder resultMsg = CrossUnionWarProto.CrossUnionWarBattleResultSyncMsg.newBuilder();
//        int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
//        Set<Long> needSyncServerId = CrossUnionServerGroupMgr.getGroupServer(groupId);
//        resultMsg.setActivityId(syncMsg.getActivityId());
//        resultMsg.setPhase(syncMsg.getPhase());
//        resultMsg.setSession(syncMsg.getSession());
//        for(CrossUnionWarProto.CrossUnionWarUnionBattleTempMsg tempMsg : syncMsg.getUnionDataListList()){
//            if(tempMsg.getIsTopMatch() || needSyncServerId.contains(tempMsg.getUnionBaseInfo().getServerId()) ||
//                    (tempMsg.hasEnemyUnionBaseInfo() && needSyncServerId.contains(tempMsg.getEnemyUnionBaseInfo().getServerId()))){
//                resultMsg.addUnionDataList(tempMsg.toBuilder());
//            }
//        }
        return syncMsg;
    }

    public static Map<Integer, List<CrossUnionWarSimple>> getUnionWarSimpleMap() {
        return unionWarSimpleMap;
    }

    public static Map<Integer, Map<Integer, Map<Integer, List<CrossUnionWarState>>>> getUnionWarStateMap() {
        return unionWarStateMap;
    }

    public static void repair(int activityId) {


    }

    public static List<Integer> getGroupListByCrossServerId(int activityId, long crossServerId){
        Map<Integer, UnionActivityGroup> groupMap = Cross2UnionActivityGroupMgr.getGroupMap(activityId);
        if(groupMap == null){
            return new ArrayList<>();
        }
        List<Integer> groupIdList = new ArrayList<>();
        for (Map.Entry<Integer, UnionActivityGroup> groupEntry : groupMap.entrySet()) {
            if(groupEntry.getValue().getCrossServerId() == crossServerId){
                groupIdList.add(groupEntry.getValue().getGroupId());
            }
        }
        return groupIdList;
    }

    public static List<CrossUnionWarDetail> filterUnionDetailData(int activityId, int groupId, List<CrossUnionWarDetail> dataList) {
        Map<Integer, UnionActivityGroup> groupMap = Cross2UnionActivityGroupMgr.getGroupMap(activityId);
        if(groupMap == null || !groupMap.containsKey(groupId)){
            return new ArrayList<>();
        }
        UnionActivityGroup group = groupMap.get(groupId);
        List<String> unionList = new ArrayList<>(group.getUnionDataMap().keySet());
        if(unionList.size() == 0){
            return new ArrayList<>();
        }
        List<CrossUnionWarDetail> resultList = new ArrayList<>(dataList);
        resultList.removeIf(detail -> !unionList.contains(detail.getUnionUid()));
        return resultList;
    }

    public static List<CrossUnionWarSimple> filterUnionData(int activityId, int groupId, List<CrossUnionWarSimple> simpleList) {
        Map<Integer, UnionActivityGroup> groupMap = Cross2UnionActivityGroupMgr.getGroupMap(activityId);
        if(groupMap == null || !groupMap.containsKey(groupId)){
            return new ArrayList<>();
        }
        UnionActivityGroup group = groupMap.get(groupId);
        List<String> unionList = new ArrayList<>(group.getUnionDataMap().keySet());
        if(unionList.size() == 0){
            return new ArrayList<>();
        }
        List<CrossUnionWarSimple> resultList = new ArrayList<>(simpleList);
        resultList.removeIf(simple -> !unionList.contains(simple.getUnionUid()));
        return resultList;
    }

    public static List<Integer> getGroupListByServerId(int activityId, long serverId){
        Map<Integer, UnionActivityGroup> groupMap = Cross2UnionActivityGroupMgr.getGroupMap(activityId);
        if(groupMap == null){
            return new ArrayList<>();
        }
        List<Integer> groupIdList = new ArrayList<>();
        for (Map.Entry<Integer, UnionActivityGroup> groupEntry : groupMap.entrySet()) {
            if(groupEntry.getValue().getServerSet().contains(serverId)){
                groupIdList.add(groupEntry.getValue().getGroupId());
            }
        }
        return groupIdList;
    }

    public static List<Long> getServerListByGroupId(ActivityInfo activityInfo, int groupId){
        if(groupId == 0){
            return new ArrayList<>(activityInfo.getServerIdList());
        }
        UnionActivityGroup activityGroup = Cross2UnionActivityGroupMgr.getGroupData(activityInfo.getActivityId(), groupId);
        if(activityGroup == null){
            return new ArrayList<>(activityInfo.getServerIdList());
        }
        return new ArrayList<>(activityGroup.getServerSet());
    }
}
